summaryrefslogtreecommitdiff
path: root/apt-pkg/packagemanager.cc
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2014-05-17 12:37:13 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2014-05-22 17:43:48 +0200
commit0eb4af9d3d0c524c7afdc684238aa263ac287449 (patch)
tree61c084289cd12fb924e82af1d1092a2ee00def18 /apt-pkg/packagemanager.cc
parent71e7a0f3a432828e5bd5498297051aa37e7f0a59 (diff)
fix tight loop detection and temporary removes
As outlined in #748355 apt segfaulted if it encountered a loop between a package pre-depending on a package conflicting with the previous as it ended up in an endless loop trying to unpack 'the other package'. In this specific case as an essential package is involved a lot of force needs to be applied, but can also be caused by 'normal' tight loops and highlights a problem in how we handle breaks which we want to avoid. The fix comes in multiple entangled changes: 1. All Smart* calls are guarded with loop detection. Some already had it, some had parts of it, some did it incorrect, and some didn't even try. 2. temporary removes to avoid a loop (which is done if a loop is detected) prevent the unpack of this looping package (we tried to unpack it to avoid the conflict/breaks, but due to a loop we couldn't, so we remove/deconfigure it instead which means we can't unpack it now) 3. handle conflicts and breaks very similar instead of duplicating most of the code. The only remaining difference is, as it should: deconfigure is enough for breaks, for conflicts we need the big hammer
Diffstat (limited to 'apt-pkg/packagemanager.cc')
-rw-r--r--apt-pkg/packagemanager.cc327
1 files changed, 156 insertions, 171 deletions
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index 56f5c59c9..393f836f7 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -261,7 +261,7 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D,
if (Cache.VS().CheckDep(Ver,D->CompareOp,D.TargetVer()) == false)
continue;
- if (EarlyRemove(D.ParentPkg()) == false)
+ if (EarlyRemove(D.ParentPkg(), &D) == false)
return _error->Error("Reverse conflicts early remove for package '%s' failed",
Pkg.FullName().c_str());
}
@@ -313,18 +313,41 @@ bool pkgPackageManager::ConfigureAll()
return true;
}
/*}}}*/
+// PM::NonLoopingSmart - helper to avoid loops while calling Smart methods /*{{{*/
+// -----------------------------------------------------------------------
+/* ensures that a loop of the form A depends B, B depends A (and similar)
+ is not leading us down into infinite recursion segfault land */
+bool pkgPackageManager::NonLoopingSmart(SmartAction const action, pkgCache::PkgIterator &Pkg,
+ pkgCache::PkgIterator DepPkg, int const Depth, bool const PkgLoop,
+ bool * const Bad, bool * const Changed)
+{
+ if (PkgLoop == false)
+ List->Flag(Pkg,pkgOrderList::Loop);
+ bool success = false;
+ switch(action)
+ {
+ case UNPACK_IMMEDIATE: success = SmartUnPack(DepPkg, true, Depth + 1); break;
+ case UNPACK: success = SmartUnPack(DepPkg, false, Depth + 1); break;
+ case CONFIGURE: success = SmartConfigure(DepPkg, Depth + 1); break;
+ }
+ if (PkgLoop == false)
+ List->RmFlag(Pkg,pkgOrderList::Loop);
+
+ if (success == false)
+ return false;
+
+ if (Bad != NULL)
+ *Bad = false;
+ if (Changed != NULL && List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
+ *Changed = true;
+ return true;
+}
+ /*}}}*/
// PM::SmartConfigure - Perform immediate configuration of the pkg /*{{{*/
// ---------------------------------------------------------------------
/* This function tries to put the system in a state where Pkg can be configured.
- This involves checking each of Pkg's dependanies and unpacking and
- configuring packages where needed.
-
- Note on failure: This method can fail, without causing any problems.
- This can happen when using Immediate-Configure-All, SmartUnPack may call
- SmartConfigure, it may fail because of a complex dependency situation, but
- a error will only be reported if ConfigureAll fails. This is why some of the
- messages this function reports on failure (return false;) as just warnings
- only shown when debuging*/
+ This involves checking each of Pkg's dependencies and unpacking and
+ configuring packages where needed. */
bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
{
// If this is true, only check and correct and dependencies without the Loop flag
@@ -339,9 +362,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
}
VerIterator const instVer = Cache[Pkg].InstVerIter(Cache);
-
- /* Because of the ordered list, most dependencies should be unpacked,
- however if there is a loop (A depends on B, B depends on A) this will not
+
+ /* Because of the ordered list, most dependencies should be unpacked,
+ however if there is a loop (A depends on B, B depends on A) this will not
be the case, so check for dependencies before configuring. */
bool Bad = false, Changed = false;
const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000);
@@ -388,24 +411,15 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
if (Debug)
std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
Bad = false;
- break;
}
else
{
if (Debug)
clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl;
- if (PkgLoop == false)
- List->Flag(Pkg,pkgOrderList::Loop);
- if (SmartUnPack(DepPkg, true, Depth + 1) == false)
+ if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
return false;
- Bad = false;
- if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
- Changed = true;
- if (PkgLoop == false)
- List->RmFlag(Pkg,pkgOrderList::Loop);
- if (Bad == false)
- break;
}
+ break;
}
if (Cur == End || Bad == false)
@@ -460,22 +474,12 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
Bad = false;
break;
}
- /* Check for a loop to prevent one forming
- If A depends on B and B depends on A, SmartConfigure will
- just hop between them if this is not checked. Dont remove the
- loop flag after finishing however as loop is already set.
- This means that there is another SmartConfigure call for this
- package and it will remove the loop flag */
- if (PkgLoop == false)
- List->Flag(Pkg,pkgOrderList::Loop);
- if (SmartConfigure(DepPkg, Depth + 1) == false)
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Configure already unpacked " << DepPkg << std::endl;
+ if (NonLoopingSmart(CONFIGURE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
return false;
- Bad = false;
- if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
- Changed = true;
- if (PkgLoop == false)
- List->RmFlag(Pkg,pkgOrderList::Loop);
break;
+
}
else if (List->IsFlag(DepPkg,pkgOrderList::Configured))
{
@@ -494,16 +498,16 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
if (i++ > max_loops)
return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (2) for %s, aborting", Pkg.FullName().c_str());
} while (Changed == true);
-
+
if (Bad == true)
return _error->Error(_("Could not configure '%s'. "),Pkg.FullName().c_str());
-
+
if (PkgLoop) return true;
static std::string const conf = _config->Find("PackageManager::Configure","all");
static bool const ConfigurePkgs = (conf == "all" || conf == "smart");
- if (List->IsFlag(Pkg,pkgOrderList::Configured))
+ if (List->IsFlag(Pkg,pkgOrderList::Configured))
return _error->Error("Internal configure error on '%s'.", Pkg.FullName().c_str());
if (ConfigurePkgs == true && Configure(Pkg) == false)
@@ -536,28 +540,36 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
/* This is called to deal with conflicts arising from unpacking */
bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
{
+ return EarlyRemove(Pkg, NULL);
+}
+bool pkgPackageManager::EarlyRemove(PkgIterator Pkg, DepIterator const * const Dep)
+{
if (List->IsNow(Pkg) == false)
return true;
-
+
// Already removed it
if (List->IsFlag(Pkg,pkgOrderList::Removed) == true)
return true;
-
+
// Woops, it will not be re-installed!
if (List->IsFlag(Pkg,pkgOrderList::InList) == false)
return false;
+ // these breaks on M-A:same packages can be dealt with. They 'loop' by design
+ if (Dep != NULL && (*Dep)->Type == pkgCache::Dep::DpkgBreaks && Dep->IsMultiArchImplicit() == true)
+ return true;
+
// Essential packages get special treatment
bool IsEssential = false;
if ((Pkg->Flags & pkgCache::Flag::Essential) != 0 ||
(Pkg->Flags & pkgCache::Flag::Important) != 0)
IsEssential = true;
- /* Check for packages that are the dependents of essential packages and
+ /* Check for packages that are the dependents of essential packages and
promote them too */
if (Pkg->CurrentVer != 0)
{
- for (DepIterator D = Pkg.RevDependsList(); D.end() == false &&
+ for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false &&
IsEssential == false; ++D)
if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0 ||
@@ -574,11 +586,14 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
"but if you really want to do it, activate the "
"APT::Force-LoopBreak option."),Pkg.FullName().c_str());
}
-
+ // dpkg will auto-deconfigure it, no need for the big remove hammer
+ else if (Dep != NULL && (*Dep)->Type == pkgCache::Dep::DpkgBreaks)
+ return true;
+
bool Res = SmartRemove(Pkg);
if (Cache[Pkg].Delete() == false)
List->Flag(Pkg,pkgOrderList::Removed,pkgOrderList::States);
-
+
return Res;
}
/*}}}*/
@@ -623,13 +638,14 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
VerIterator const instVer = Cache[Pkg].InstVerIter(Cache);
- /* PreUnpack Checks: This loop checks and attempts to rectify and problems that would prevent the package being unpacked.
+ /* PreUnpack Checks: This loop checks and attempts to rectify any problems that would prevent the package being unpacked.
It addresses: PreDepends, Conflicts, Obsoletes and Breaks (DpkgBreaks). Any resolutions that do not require it should
avoid configuration (calling SmartUnpack with Immediate=true), this is because when unpacking some packages with
- complex dependency structures, trying to configure some packages while breaking the loops can complicate things .
+ complex dependency structures, trying to configure some packages while breaking the loops can complicate things.
This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured),
or by the ConfigureAll call at the end of the for loop in OrderInstall. */
- bool Changed = false;
+ bool SomethingBad = false, Changed = false;
+ bool couldBeTemporaryRemoved = Depth != 0 && List->IsFlag(Pkg,pkgOrderList::Removed) == false;
const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000);
unsigned int i = 0;
do
@@ -677,183 +693,142 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
for (Version **I = VList; *I != 0; ++I)
{
VerIterator Ver(Cache,*I);
- PkgIterator Pkg = Ver.ParentPkg();
+ PkgIterator DepPkg = Ver.ParentPkg();
// Not the install version
- if (Cache[Pkg].InstallVer != *I ||
- (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
+ if (Cache[DepPkg].InstallVer != *I ||
+ (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing))
continue;
- if (List->IsFlag(Pkg,pkgOrderList::Configured))
+ if (List->IsFlag(DepPkg,pkgOrderList::Configured))
{
Bad = false;
break;
}
// check if it needs unpack or if if configure is enough
- if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == false)
+ if (List->IsFlag(DepPkg,pkgOrderList::UnPacked) == false)
{
if (Debug)
- clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << Pkg.FullName() << endl;
- // SmartUnpack with the ImmediateFlag to ensure its really ready
- if (SmartUnPack(Pkg, true, Depth + 1) == false)
+ clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << DepPkg.FullName() << endl;
+ if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
return false;
- Bad = false;
- if (List->IsFlag(Pkg,pkgOrderList::Loop) == false)
- Changed = true;
- break;
}
else
{
if (Debug)
- clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << Pkg.FullName() << endl;
- if (SmartConfigure(Pkg, Depth + 1) == false)
+ clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << DepPkg.FullName() << endl;
+ if (NonLoopingSmart(CONFIGURE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false)
return false;
- Bad = false;
- if (List->IsFlag(Pkg,pkgOrderList::Loop) == false)
- Changed = true;
- break;
}
+ break;
}
}
if (Bad == true)
- {
- if (Start == End)
- return _error->Error("Couldn't configure pre-depend %s for %s, "
- "probably a dependency cycle.",
- End.TargetPkg().FullName().c_str(),Pkg.FullName().c_str());
- }
- else
- continue;
+ SomethingBad = true;
}
else if (End->Type == pkgCache::Dep::Conflicts ||
- End->Type == pkgCache::Dep::Obsoletes)
+ End->Type == pkgCache::Dep::Obsoletes ||
+ End->Type == pkgCache::Dep::DpkgBreaks)
{
- /* Look for conflicts. Two packages that are both in the install
- state cannot conflict so we don't check.. */
SPtrArray<Version *> VList = End.AllTargets();
- for (Version **I = VList; *I != 0; I++)
+ for (Version **I = VList; *I != 0; ++I)
{
VerIterator Ver(Cache,*I);
PkgIterator ConflictPkg = Ver.ParentPkg();
- VerIterator InstallVer(Cache,Cache[ConflictPkg].InstallVer);
+ if (ConflictPkg.CurrentVer() != Ver)
+ {
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Ignore not-installed version " << Ver.VerStr() << " of " << ConflictPkg.FullName() << " for " << End << std::endl;
+ continue;
+ }
+
+ if (List->IsNow(ConflictPkg) == false)
+ {
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Ignore already dealt-with version " << Ver.VerStr() << " of " << ConflictPkg.FullName() << " for " << End << std::endl;
+ continue;
+ }
- // See if the current version is conflicting
- if (ConflictPkg.CurrentVer() == Ver && List->IsNow(ConflictPkg))
+ if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == true)
{
if (Debug)
- clog << OutputInDepth(Depth) << Pkg.FullName() << " conflicts with " << ConflictPkg.FullName() << endl;
- /* If a loop is not present or has not yet been detected, attempt to unpack packages
- to resolve this conflict. If there is a loop present, remove packages to resolve this conflict */
- if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) == false)
+ clog << OutputInDepth(Depth) << "Ignoring " << End << " as " << ConflictPkg.FullName() << "was temporarily removed" << endl;
+ continue;
+ }
+
+ if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) && PkgLoop)
+ {
+ if (End->Type == pkgCache::Dep::DpkgBreaks && End.IsMultiArchImplicit() == true)
{
- if (Cache[ConflictPkg].Keep() == 0 && Cache[ConflictPkg].InstallVer != 0)
- {
- if (Debug)
- clog << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.FullName() << " to prevent conflict" << endl;
- List->Flag(Pkg,pkgOrderList::Loop);
- if (SmartUnPack(ConflictPkg,false, Depth + 1) == false)
- return false;
- if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) == false)
- Changed = true;
- // Remove loop to allow it to be used later if needed
- List->RmFlag(Pkg,pkgOrderList::Loop);
- }
- else if (EarlyRemove(ConflictPkg) == false)
- return _error->Error("Internal Error, Could not early remove %s (1)",ConflictPkg.FullName().c_str());
+ if (Debug)
+ clog << OutputInDepth(Depth) << "Because dependency is MultiArchImplicit we ignored looping on: " << ConflictPkg << endl;
+ continue;
}
- else if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == false)
+ if (Debug)
{
- if (Debug)
+ if (End->Type == pkgCache::Dep::DpkgBreaks)
+ clog << OutputInDepth(Depth) << "Because of breaks knot, deconfigure " << ConflictPkg.FullName() << " temporarily" << endl;
+ else
clog << OutputInDepth(Depth) << "Because of conflict knot, removing " << ConflictPkg.FullName() << " temporarily" << endl;
- if (EarlyRemove(ConflictPkg) == false)
- return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str());
}
- }
- }
- }
- else if (End->Type == pkgCache::Dep::DpkgBreaks)
- {
- SPtrArray<Version *> VList = End.AllTargets();
- for (Version **I = VList; *I != 0; ++I)
- {
- VerIterator Ver(Cache,*I);
- PkgIterator BrokenPkg = Ver.ParentPkg();
- if (BrokenPkg.CurrentVer() != Ver)
- {
- if (Debug)
- std::clog << OutputInDepth(Depth) << " Ignore not-installed version " << Ver.VerStr() << " of " << Pkg.FullName() << " for " << End << std::endl;
+ if (EarlyRemove(ConflictPkg, &End) == false)
+ return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str());
+ SomethingBad = true;
continue;
}
- // Check if it needs to be unpacked
- if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false &&
- List->IsNow(BrokenPkg))
+ if (Cache[ConflictPkg].Delete() == false)
{
- if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop)
+ if (Debug)
{
- // This dependency has already been dealt with by another SmartUnPack on Pkg
- break;
+ clog << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.FullName() << " to avoid " << End;
+ if (PkgLoop == true)
+ clog << " (Looping)";
+ clog << std::endl;
}
- else
+ // we would like to avoid temporary removals and all that at best via a simple unpack
+ _error->PushToStack();
+ if (NonLoopingSmart(UNPACK, Pkg, ConflictPkg, Depth, PkgLoop, NULL, &Changed) == false)
{
- // Found a break, so see if we can unpack the package to avoid it
- // but do not set loop if another SmartUnPack already deals with it
- // Also, avoid it if the package we would unpack pre-depends on this one
- VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
- bool circle = false;
- for (pkgCache::DepIterator D = InstallVer.DependsList(); D.end() == false; ++D)
+ // but if it fails ignore this failure and look for alternative ways of solving
+ if (Debug)
{
- if (D->Type != pkgCache::Dep::PreDepends)
- continue;
- SPtrArray<Version *> VL = D.AllTargets();
- for (Version **I = VL; *I != 0; ++I)
- {
- VerIterator V(Cache,*I);
- PkgIterator P = V.ParentPkg();
- // we are checking for installation as an easy 'protection' against or-groups and (unchosen) providers
- if (P != Pkg || (P.CurrentVer() != V && Cache[P].InstallVer != V))
- continue;
- circle = true;
- break;
- }
- if (circle == true)
- break;
+ clog << OutputInDepth(Depth) << "Avoidance unpack of " << ConflictPkg.FullName() << " failed for " << End << std::endl;
+ _error->DumpErrors(std::clog);
+ }
+ _error->RevertToStack();
+ // ignorance can only happen if a) one of the offenders is already gone
+ if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == true)
+ {
+ if (Debug)
+ clog << OutputInDepth(Depth) << "But " << ConflictPkg.FullName() << " was temporarily removed in the meantime to satisfy " << End << endl;
}
- if (circle == true)
+ else if (List->IsFlag(Pkg,pkgOrderList::Removed) == true)
{
if (Debug)
- clog << OutputInDepth(Depth) << " Avoiding " << End << " avoided as " << BrokenPkg.FullName() << " has a pre-depends on " << Pkg.FullName() << std::endl;
- continue;
+ clog << OutputInDepth(Depth) << "But " << Pkg.FullName() << " was temporarily removed in the meantime to satisfy " << End << endl;
}
+ // or b) we can make one go (removal or dpkg auto-deconfigure)
else
{
if (Debug)
- {
- clog << OutputInDepth(Depth) << " Unpacking " << BrokenPkg.FullName() << " to avoid " << End;
- if (PkgLoop == true)
- clog << " (Looping)";
- clog << std::endl;
- }
- if (PkgLoop == false)
- List->Flag(Pkg,pkgOrderList::Loop);
- if (SmartUnPack(BrokenPkg, false, Depth + 1) == false)
- return false;
- if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) == false)
- Changed = true;
- if (PkgLoop == false)
- List->RmFlag(Pkg,pkgOrderList::Loop);
+ clog << OutputInDepth(Depth) << "So temprorary remove/deconfigure " << ConflictPkg.FullName() << " to satisfy " << End << endl;
+ if (EarlyRemove(ConflictPkg, &End) == false)
+ return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str());
}
}
+ else
+ _error->MergeWithStack();
}
- // Check if a package needs to be removed
- else if (Cache[BrokenPkg].Delete() == true && List->IsFlag(BrokenPkg,pkgOrderList::Configured) == false)
+ else
{
if (Debug)
- clog << OutputInDepth(Depth) << " Removing " << BrokenPkg.FullName() << " to avoid " << End << endl;
- if (SmartRemove(BrokenPkg) == false)
- return false;
+ clog << OutputInDepth(Depth) << "Removing " << ConflictPkg.FullName() << " now to avoid " << End << endl;
+ // no earlyremove() here as user has already agreed to the permanent removal
+ if (SmartRemove(Pkg) == false)
+ return _error->Error("Internal Error, Could not early remove %s (1)",ConflictPkg.FullName().c_str());
}
}
}
@@ -861,7 +836,17 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
if (i++ > max_loops)
return _error->Error("Internal error: APT::pkgPackageManager::MaxLoopCount reached in SmartConfigure for %s, aborting", Pkg.FullName().c_str());
} while (Changed == true);
-
+
+ if (SomethingBad == true)
+ return _error->Error("Couldn't configure %s, probably a dependency cycle.", Pkg.FullName().c_str());
+
+ if (couldBeTemporaryRemoved == true && List->IsFlag(Pkg,pkgOrderList::Removed) == true)
+ {
+ if (Debug)
+ std::clog << OutputInDepth(Depth) << "Prevent unpack as " << Pkg << " is currently temporarily removed" << std::endl;
+ return true;
+ }
+
// Check for reverse conflicts.
if (CheckRConflicts(Pkg,Pkg.RevDependsList(),
instVer.VerStr()) == false)
@@ -922,7 +907,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
if (Immediate == true) {
// Perform immedate configuration of the package.
if (SmartConfigure(Pkg, Depth + 1) == false)
- _error->Warning(_("Could not perform immediate configuration on '%s'. "
+ _error->Error(_("Could not perform immediate configuration on '%s'. "
"Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.FullName().c_str(),2);
}