|
@@ -17,6 +17,7 @@
|
|
|
#include <apt-pkg/fileutl.h>
|
|
#include <apt-pkg/fileutl.h>
|
|
|
#include <apt-pkg/strutl.h>
|
|
#include <apt-pkg/strutl.h>
|
|
|
#include <apt-pkg/configuration.h>
|
|
#include <apt-pkg/configuration.h>
|
|
|
|
|
+#include <apt-pkg/aptconfiguration.h>
|
|
|
#include <apt-pkg/pkgsystem.h>
|
|
#include <apt-pkg/pkgsystem.h>
|
|
|
#include <apt-pkg/tagfile.h>
|
|
#include <apt-pkg/tagfile.h>
|
|
|
|
|
|
|
@@ -164,34 +165,46 @@ bool pkgDepCache::Init(OpProgress *Prog)
|
|
|
bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/
|
|
bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/
|
|
|
{
|
|
{
|
|
|
FileFd state_file;
|
|
FileFd state_file;
|
|
|
- string state = _config->FindDir("Dir::State") + "extended_states";
|
|
|
|
|
|
|
+ string const state = _config->FindFile("Dir::State::extended_states");
|
|
|
if(FileExists(state)) {
|
|
if(FileExists(state)) {
|
|
|
state_file.Open(state, FileFd::ReadOnly);
|
|
state_file.Open(state, FileFd::ReadOnly);
|
|
|
- int file_size = state_file.Size();
|
|
|
|
|
|
|
+ int const file_size = state_file.Size();
|
|
|
if(Prog != NULL)
|
|
if(Prog != NULL)
|
|
|
Prog->OverallProgress(0, file_size, 1,
|
|
Prog->OverallProgress(0, file_size, 1,
|
|
|
_("Reading state information"));
|
|
_("Reading state information"));
|
|
|
|
|
|
|
|
pkgTagFile tagfile(&state_file);
|
|
pkgTagFile tagfile(&state_file);
|
|
|
pkgTagSection section;
|
|
pkgTagSection section;
|
|
|
- int amt=0;
|
|
|
|
|
- bool debug_autoremove=_config->FindB("Debug::pkgAutoRemove",false);
|
|
|
|
|
|
|
+ int amt = 0;
|
|
|
|
|
+ bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
|
|
|
while(tagfile.Step(section)) {
|
|
while(tagfile.Step(section)) {
|
|
|
- string pkgname = section.FindS("Package");
|
|
|
|
|
- pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
|
|
|
|
|
- // Silently ignore unknown packages and packages with no actual
|
|
|
|
|
- // version.
|
|
|
|
|
- if(!pkg.end() && !pkg.VersionList().end()) {
|
|
|
|
|
- short reason = section.FindI("Auto-Installed", 0);
|
|
|
|
|
- if(reason > 0)
|
|
|
|
|
- PkgState[pkg->ID].Flags |= Flag::Auto;
|
|
|
|
|
- if(debug_autoremove)
|
|
|
|
|
- std::clog << "Auto-Installed : " << pkgname << std::endl;
|
|
|
|
|
- amt+=section.size();
|
|
|
|
|
- if(Prog != NULL)
|
|
|
|
|
- Prog->OverallProgress(amt, file_size, 1,
|
|
|
|
|
- _("Reading state information"));
|
|
|
|
|
|
|
+ string const pkgname = section.FindS("Package");
|
|
|
|
|
+ string pkgarch = section.FindS("Architecture");
|
|
|
|
|
+ if (pkgarch.empty() == true)
|
|
|
|
|
+ pkgarch = "any";
|
|
|
|
|
+ pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch);
|
|
|
|
|
+ // Silently ignore unknown packages and packages with no actual version.
|
|
|
|
|
+ if(pkg.end() == true || pkg->VersionList == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ short const reason = section.FindI("Auto-Installed", 0);
|
|
|
|
|
+ if(reason > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ PkgState[pkg->ID].Flags |= Flag::Auto;
|
|
|
|
|
+ if (unlikely(debug_autoremove))
|
|
|
|
|
+ std::clog << "Auto-Installed : " << pkg.FullName() << std::endl;
|
|
|
|
|
+ if (pkgarch == "any")
|
|
|
|
|
+ {
|
|
|
|
|
+ pkgCache::GrpIterator G = pkg.Group();
|
|
|
|
|
+ for (pkg = G.NextPkg(pkg); pkg.end() != true; pkg = G.NextPkg(pkg))
|
|
|
|
|
+ if (pkg->VersionList != 0)
|
|
|
|
|
+ PkgState[pkg->ID].Flags |= Flag::Auto;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ amt += section.size();
|
|
|
|
|
+ if(Prog != NULL)
|
|
|
|
|
+ Prog->OverallProgress(amt, file_size, 1,
|
|
|
|
|
+ _("Reading state information"));
|
|
|
}
|
|
}
|
|
|
if(Prog != NULL)
|
|
if(Prog != NULL)
|
|
|
Prog->OverallProgress(file_size, file_size, 1,
|
|
Prog->OverallProgress(file_size, file_size, 1,
|
|
@@ -203,13 +216,13 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/
|
|
bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/
|
|
|
{
|
|
{
|
|
|
- bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
|
|
|
|
|
|
|
+ bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
|
|
|
|
|
|
|
|
if(debug_autoremove)
|
|
if(debug_autoremove)
|
|
|
std::clog << "pkgDepCache::writeStateFile()" << std::endl;
|
|
std::clog << "pkgDepCache::writeStateFile()" << std::endl;
|
|
|
|
|
|
|
|
FileFd StateFile;
|
|
FileFd StateFile;
|
|
|
- string state = _config->FindDir("Dir::State") + "extended_states";
|
|
|
|
|
|
|
+ string const state = _config->FindFile("Dir::State::extended_states");
|
|
|
|
|
|
|
|
// if it does not exist, create a empty one
|
|
// if it does not exist, create a empty one
|
|
|
if(!FileExists(state))
|
|
if(!FileExists(state))
|
|
@@ -224,7 +237,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/
|
|
|
state.c_str());
|
|
state.c_str());
|
|
|
|
|
|
|
|
FILE *OutFile;
|
|
FILE *OutFile;
|
|
|
- string outfile = state + ".tmp";
|
|
|
|
|
|
|
+ string const outfile = state + ".tmp";
|
|
|
if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
|
|
if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
|
|
|
return _error->Error(_("Failed to write temporary StateFile %s"),
|
|
return _error->Error(_("Failed to write temporary StateFile %s"),
|
|
|
outfile.c_str());
|
|
outfile.c_str());
|
|
@@ -235,46 +248,72 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly) /*{{{*/
|
|
|
std::set<string> pkgs_seen;
|
|
std::set<string> pkgs_seen;
|
|
|
const char *nullreorderlist[] = {0};
|
|
const char *nullreorderlist[] = {0};
|
|
|
while(tagfile.Step(section)) {
|
|
while(tagfile.Step(section)) {
|
|
|
- string pkgname = section.FindS("Package");
|
|
|
|
|
|
|
+ string const pkgname = section.FindS("Package");
|
|
|
|
|
+ string pkgarch = section.FindS("Architecture");
|
|
|
|
|
+ if (pkgarch.empty() == true)
|
|
|
|
|
+ pkgarch = "native";
|
|
|
// Silently ignore unknown packages and packages with no actual
|
|
// Silently ignore unknown packages and packages with no actual
|
|
|
// version.
|
|
// version.
|
|
|
- pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
|
|
|
|
|
|
|
+ pkgCache::PkgIterator pkg = Cache->FindPkg(pkgname, pkgarch);
|
|
|
if(pkg.end() || pkg.VersionList().end())
|
|
if(pkg.end() || pkg.VersionList().end())
|
|
|
continue;
|
|
continue;
|
|
|
- bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
|
|
|
|
|
|
|
+ StateCache const &P = PkgState[pkg->ID];
|
|
|
|
|
+ bool newAuto = (P.Flags & Flag::Auto);
|
|
|
|
|
+ // skip not installed or now-removed ones if requested
|
|
|
|
|
+ if (InstalledOnly && (
|
|
|
|
|
+ (pkg->CurrentVer == 0 && P.Mode != ModeInstall) ||
|
|
|
|
|
+ (pkg->CurrentVer != 0 && P.Mode == ModeDelete)))
|
|
|
|
|
+ {
|
|
|
|
|
+ // The section is obsolete if it contains no other tag
|
|
|
|
|
+ unsigned int const count = section.Count();
|
|
|
|
|
+ if (count < 2 ||
|
|
|
|
|
+ (count == 2 && section.Exists("Auto-Installed")) ||
|
|
|
|
|
+ (count == 3 && section.Exists("Auto-Installed") && section.Exists("Architecture")))
|
|
|
|
|
+ continue;
|
|
|
|
|
+ else
|
|
|
|
|
+ newAuto = false;
|
|
|
|
|
+ }
|
|
|
if(_config->FindB("Debug::pkgAutoRemove",false))
|
|
if(_config->FindB("Debug::pkgAutoRemove",false))
|
|
|
std::clog << "Update existing AutoInstall info: "
|
|
std::clog << "Update existing AutoInstall info: "
|
|
|
- << pkg.Name() << std::endl;
|
|
|
|
|
- TFRewriteData rewrite[2];
|
|
|
|
|
- rewrite[0].Tag = "Auto-Installed";
|
|
|
|
|
- rewrite[0].Rewrite = newAuto ? "1" : "0";
|
|
|
|
|
|
|
+ << pkg.FullName() << std::endl;
|
|
|
|
|
+ TFRewriteData rewrite[3];
|
|
|
|
|
+ rewrite[0].Tag = "Architecture";
|
|
|
|
|
+ rewrite[0].Rewrite = pkg.Arch();
|
|
|
rewrite[0].NewTag = 0;
|
|
rewrite[0].NewTag = 0;
|
|
|
- rewrite[1].Tag = 0;
|
|
|
|
|
|
|
+ rewrite[1].Tag = "Auto-Installed";
|
|
|
|
|
+ rewrite[1].Rewrite = newAuto ? "1" : "0";
|
|
|
|
|
+ rewrite[1].NewTag = 0;
|
|
|
|
|
+ rewrite[2].Tag = 0;
|
|
|
TFRewrite(OutFile, section, nullreorderlist, rewrite);
|
|
TFRewrite(OutFile, section, nullreorderlist, rewrite);
|
|
|
fprintf(OutFile,"\n");
|
|
fprintf(OutFile,"\n");
|
|
|
- pkgs_seen.insert(pkgname);
|
|
|
|
|
|
|
+ pkgs_seen.insert(pkg.FullName());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// then write the ones we have not seen yet
|
|
// then write the ones we have not seen yet
|
|
|
std::ostringstream ostr;
|
|
std::ostringstream ostr;
|
|
|
for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
|
|
for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
|
|
|
- if(PkgState[pkg->ID].Flags & Flag::Auto) {
|
|
|
|
|
- if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
|
|
|
|
|
|
|
+ StateCache const &P = PkgState[pkg->ID];
|
|
|
|
|
+ if(P.Flags & Flag::Auto) {
|
|
|
|
|
+ if (pkgs_seen.find(pkg.FullName()) != pkgs_seen.end()) {
|
|
|
if(debug_autoremove)
|
|
if(debug_autoremove)
|
|
|
- std::clog << "Skipping already written " << pkg.Name() << std::endl;
|
|
|
|
|
|
|
+ std::clog << "Skipping already written " << pkg.FullName() << std::endl;
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
- // skip not installed ones if requested
|
|
|
|
|
- if(InstalledOnly && pkg->CurrentVer == 0)
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ // skip not installed ones if requested
|
|
|
|
|
+ if (InstalledOnly && (
|
|
|
|
|
+ (pkg->CurrentVer == 0 && P.Mode != ModeInstall) ||
|
|
|
|
|
+ (pkg->CurrentVer != 0 && P.Mode == ModeDelete)))
|
|
|
|
|
+ continue;
|
|
|
|
|
+ const char* const pkgarch = pkg.Arch();
|
|
|
|
|
+ if (strcmp(pkgarch, "all") == 0)
|
|
|
|
|
+ continue;
|
|
|
if(debug_autoremove)
|
|
if(debug_autoremove)
|
|
|
- std::clog << "Writing new AutoInstall: "
|
|
|
|
|
- << pkg.Name() << std::endl;
|
|
|
|
|
|
|
+ std::clog << "Writing new AutoInstall: " << pkg.FullName() << std::endl;
|
|
|
ostr.str(string(""));
|
|
ostr.str(string(""));
|
|
|
- ostr << "Package: " << pkg.Name()
|
|
|
|
|
|
|
+ ostr << "Package: " << pkg.Name()
|
|
|
|
|
+ << "\nArchitecture: " << pkgarch
|
|
|
<< "\nAuto-Installed: 1\n\n";
|
|
<< "\nAuto-Installed: 1\n\n";
|
|
|
fprintf(OutFile,"%s",ostr.str().c_str());
|
|
fprintf(OutFile,"%s",ostr.str().c_str());
|
|
|
- fprintf(OutFile,"\n");
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
fclose(OutFile);
|
|
fclose(OutFile);
|
|
@@ -299,7 +338,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
|
|
|
/* Check simple depends. A depends -should- never self match but
|
|
/* Check simple depends. A depends -should- never self match but
|
|
|
we allow it anyhow because dpkg does. Technically it is a packaging
|
|
we allow it anyhow because dpkg does. Technically it is a packaging
|
|
|
bug. Conflicts may never self match */
|
|
bug. Conflicts may never self match */
|
|
|
- if (Dep.TargetPkg() != Dep.ParentPkg() ||
|
|
|
|
|
|
|
+ if (Dep.TargetPkg()->Group != Dep.ParentPkg()->Group ||
|
|
|
(Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
|
|
(Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
|
|
|
{
|
|
{
|
|
|
PkgIterator Pkg = Dep.TargetPkg();
|
|
PkgIterator Pkg = Dep.TargetPkg();
|
|
@@ -328,9 +367,9 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
|
|
|
PkgIterator Pkg = Dep.ParentPkg();
|
|
PkgIterator Pkg = Dep.ParentPkg();
|
|
|
for (; P.end() != true; P++)
|
|
for (; P.end() != true; P++)
|
|
|
{
|
|
{
|
|
|
- /* Provides may never be applied against the same package if it is
|
|
|
|
|
- a conflicts. See the comment above. */
|
|
|
|
|
- if (P.OwnerPkg() == Pkg &&
|
|
|
|
|
|
|
+ /* 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))
|
|
(Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
@@ -368,8 +407,11 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
// DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
|
|
// DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
|
-/* Call with Mult = -1 to preform the inverse opration */
|
|
|
|
|
-void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
|
|
|
|
|
|
|
+/* Call with Mult = -1 to preform the inverse opration
|
|
|
|
|
+ The Mult increases the complexity of the calulations here and is unused -
|
|
|
|
|
+ or do we really have a usecase for removing the size of a package two
|
|
|
|
|
+ times? So let us replace it with a simple bool and be done with it… */
|
|
|
|
|
+__deprecated void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
|
|
|
{
|
|
{
|
|
|
StateCache &P = PkgState[Pkg->ID];
|
|
StateCache &P = PkgState[Pkg->ID];
|
|
|
|
|
|
|
@@ -383,8 +425,8 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
|
|
|
// Compute the size data
|
|
// Compute the size data
|
|
|
if (P.NewInstall() == true)
|
|
if (P.NewInstall() == true)
|
|
|
{
|
|
{
|
|
|
- iUsrSize += (signed)(Mult*P.InstVerIter(*this)->InstalledSize);
|
|
|
|
|
- iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
|
|
|
|
|
|
|
+ iUsrSize += (signed long long)(Mult*P.InstVerIter(*this)->InstalledSize);
|
|
|
|
|
+ iDownloadSize += (signed long long)(Mult*P.InstVerIter(*this)->Size);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -393,9 +435,9 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
|
|
|
(P.InstallVer != (Version *)Pkg.CurrentVer() ||
|
|
(P.InstallVer != (Version *)Pkg.CurrentVer() ||
|
|
|
(P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
|
|
(P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
|
|
|
{
|
|
{
|
|
|
- iUsrSize += (signed)(Mult*((signed)P.InstVerIter(*this)->InstalledSize -
|
|
|
|
|
- (signed)Pkg.CurrentVer()->InstalledSize));
|
|
|
|
|
- iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
|
|
|
|
|
|
|
+ iUsrSize += (signed long long)(Mult*((signed long long)P.InstVerIter(*this)->InstalledSize -
|
|
|
|
|
+ (signed long long)Pkg.CurrentVer()->InstalledSize));
|
|
|
|
|
+ iDownloadSize += (signed long long)(Mult*P.InstVerIter(*this)->Size);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -403,14 +445,80 @@ void pkgDepCache::AddSizes(const PkgIterator &Pkg,signed long Mult)
|
|
|
if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
|
|
if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
|
|
|
P.Delete() == false)
|
|
P.Delete() == false)
|
|
|
{
|
|
{
|
|
|
- iDownloadSize += (signed)(Mult*P.InstVerIter(*this)->Size);
|
|
|
|
|
|
|
+ iDownloadSize += (signed long long)(Mult*P.InstVerIter(*this)->Size);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Removing
|
|
// Removing
|
|
|
if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
|
|
if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
|
|
|
{
|
|
{
|
|
|
- iUsrSize -= (signed)(Mult*Pkg.CurrentVer()->InstalledSize);
|
|
|
|
|
|
|
+ iUsrSize -= (signed long long)(Mult*Pkg.CurrentVer()->InstalledSize);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+ /*}}}*/
|
|
|
|
|
+// DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
|
|
|
|
|
+// ---------------------------------------------------------------------
|
|
|
|
|
+/* Call with Inverse = true to preform the inverse opration */
|
|
|
|
|
+void pkgDepCache::AddSizes(const PkgIterator &Pkg, bool const &Inverse)
|
|
|
|
|
+{
|
|
|
|
|
+ StateCache &P = PkgState[Pkg->ID];
|
|
|
|
|
+
|
|
|
|
|
+ if (Pkg->VersionList == 0)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
|
|
|
|
|
+ P.Keep() == true)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ // Compute the size data
|
|
|
|
|
+ if (P.NewInstall() == true)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (Inverse == false) {
|
|
|
|
|
+ iUsrSize += P.InstVerIter(*this)->InstalledSize;
|
|
|
|
|
+ iDownloadSize += P.InstVerIter(*this)->Size;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ iUsrSize -= P.InstVerIter(*this)->InstalledSize;
|
|
|
|
|
+ iDownloadSize -= P.InstVerIter(*this)->Size;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Upgrading
|
|
|
|
|
+ if (Pkg->CurrentVer != 0 &&
|
|
|
|
|
+ (P.InstallVer != (Version *)Pkg.CurrentVer() ||
|
|
|
|
|
+ (P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (Inverse == false) {
|
|
|
|
|
+ iUsrSize -= Pkg.CurrentVer()->InstalledSize;
|
|
|
|
|
+ iUsrSize += P.InstVerIter(*this)->InstalledSize;
|
|
|
|
|
+ iDownloadSize += P.InstVerIter(*this)->Size;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ iUsrSize -= P.InstVerIter(*this)->InstalledSize;
|
|
|
|
|
+ iUsrSize += Pkg.CurrentVer()->InstalledSize;
|
|
|
|
|
+ iDownloadSize -= P.InstVerIter(*this)->Size;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Reinstall
|
|
|
|
|
+ if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
|
|
|
|
|
+ P.Delete() == false)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (Inverse == false)
|
|
|
|
|
+ iDownloadSize += P.InstVerIter(*this)->Size;
|
|
|
|
|
+ else
|
|
|
|
|
+ iDownloadSize -= P.InstVerIter(*this)->Size;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Removing
|
|
|
|
|
+ if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (Inverse == false)
|
|
|
|
|
+ iUsrSize -= Pkg.CurrentVer()->InstalledSize;
|
|
|
|
|
+ else
|
|
|
|
|
+ iUsrSize += Pkg.CurrentVer()->InstalledSize;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -596,6 +704,107 @@ void pkgDepCache::UpdateVerState(PkgIterator Pkg)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
|
|
+// DepCache::RemovePseudoInstalledPkg - MultiArch helper for Update() /*{{{*/
|
|
|
|
|
+// ---------------------------------------------------------------------
|
|
|
|
|
+/* We "install" arch all packages for all archs if it is installed. Many
|
|
|
|
|
+ of these will be broken. This method will look at these broken Pkg and
|
|
|
|
|
+ "remove" it. */
|
|
|
|
|
+bool pkgDepCache::RemovePseudoInstalledPkg(PkgIterator &Pkg, std::set<unsigned long> &recheck) {
|
|
|
|
|
+ if (unlikely(Pkg->CurrentVer == 0))
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ VerIterator V = Pkg.CurrentVer();
|
|
|
|
|
+ if (V->MultiArch != Version::All)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ // Never ever kill an "all" package - they have no dependency so they can't be broken
|
|
|
|
|
+ if (strcmp(Pkg.Arch(),"all") == 0)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ unsigned char const CurDepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy);
|
|
|
|
|
+ if ((CurDepState & DepInstMin) == DepInstMin) {
|
|
|
|
|
+ // okay, the package isn't broken, but is the package also required?
|
|
|
|
|
+ // If it has no real dependencies, no installed rdepends and doesn't
|
|
|
|
|
+ // provide something of value, we will kill it as not required.
|
|
|
|
|
+ // These pseudopackages have otherwise interesting effects if they get
|
|
|
|
|
+ // a new dependency in a newer version…
|
|
|
|
|
+ for (pkgCache::DepIterator D = V.DependsList();
|
|
|
|
|
+ D.end() != true; ++D)
|
|
|
|
|
+ if (D.IsCritical() == true && D.ParentPkg()->Group != Pkg->Group)
|
|
|
|
|
+ return false;
|
|
|
|
|
+ for (DepIterator D = Pkg.RevDependsList(); D.end() != true; ++D)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (D.IsCritical() == false)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ PkgIterator const P = D.ParentPkg();
|
|
|
|
|
+ if (P->Group == Pkg->Group)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (P->CurrentVer != 0)
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (PrvIterator Prv = V.ProvidesList(); Prv.end() != true; Prv++)
|
|
|
|
|
+ for (DepIterator d = Prv.ParentPkg().RevDependsList();
|
|
|
|
|
+ d.end() != true; ++d)
|
|
|
|
|
+ {
|
|
|
|
|
+ PkgIterator const P = d.ParentPkg();
|
|
|
|
|
+ if (P->CurrentVer != 0 &&
|
|
|
|
|
+ P->Group != Pkg->Group)
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Dependencies for this arch all package are not statisfied
|
|
|
|
|
+ // so we installed it only for our convenience: get right of it now.
|
|
|
|
|
+ RemoveSizes(Pkg);
|
|
|
|
|
+ RemoveStates(Pkg);
|
|
|
|
|
+
|
|
|
|
|
+ Pkg->CurrentVer = 0;
|
|
|
|
|
+ PkgState[Pkg->ID].InstallVer = 0;
|
|
|
|
|
+
|
|
|
|
|
+ AddStates(Pkg);
|
|
|
|
|
+ Update(Pkg);
|
|
|
|
|
+ AddSizes(Pkg);
|
|
|
|
|
+
|
|
|
|
|
+ // After the remove previously satisfied pseudo pkg could be now
|
|
|
|
|
+ // no longer satisfied, so we need to recheck the reverse dependencies
|
|
|
|
|
+ for (DepIterator d = Pkg.RevDependsList(); d.end() != true; ++d)
|
|
|
|
|
+ {
|
|
|
|
|
+ PkgIterator const P = d.ParentPkg();
|
|
|
|
|
+ if (P->CurrentVer != 0)
|
|
|
|
|
+ recheck.insert(P.Index());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (DepIterator d = V.DependsList(); d.end() != true; ++d)
|
|
|
|
|
+ {
|
|
|
|
|
+ PkgIterator const P = d.TargetPkg();
|
|
|
|
|
+ for (PrvIterator Prv = P.ProvidesList(); Prv.end() != true; ++Prv)
|
|
|
|
|
+ {
|
|
|
|
|
+ PkgIterator const O = Prv.OwnerPkg();
|
|
|
|
|
+ if (O->CurrentVer != 0)
|
|
|
|
|
+ recheck.insert(O.Index());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (P->CurrentVer != 0)
|
|
|
|
|
+ recheck.insert(P.Index());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (PrvIterator Prv = V.ProvidesList(); Prv.end() != true; Prv++)
|
|
|
|
|
+ {
|
|
|
|
|
+ for (DepIterator d = Prv.ParentPkg().RevDependsList();
|
|
|
|
|
+ d.end() != true; ++d)
|
|
|
|
|
+ {
|
|
|
|
|
+ PkgIterator const P = d.ParentPkg();
|
|
|
|
|
+ if (P->CurrentVer == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ recheck.insert(P.Index());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+ /*}}}*/
|
|
|
// DepCache::Update - Figure out all the state information /*{{{*/
|
|
// DepCache::Update - Figure out all the state information /*{{{*/
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
|
/* This will figure out the state of all the packages and all the
|
|
/* This will figure out the state of all the packages and all the
|
|
@@ -609,9 +818,13 @@ void pkgDepCache::Update(OpProgress *Prog)
|
|
|
iKeepCount = 0;
|
|
iKeepCount = 0;
|
|
|
iBrokenCount = 0;
|
|
iBrokenCount = 0;
|
|
|
iBadCount = 0;
|
|
iBadCount = 0;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ std::set<unsigned long> recheck;
|
|
|
|
|
+
|
|
|
// Perform the depends pass
|
|
// Perform the depends pass
|
|
|
int Done = 0;
|
|
int Done = 0;
|
|
|
|
|
+ bool const checkMultiArch = APT::Configuration::getArchitectures().size() > 1;
|
|
|
|
|
+ unsigned long killed = 0;
|
|
|
for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
|
|
for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
|
|
|
{
|
|
{
|
|
|
if (Prog != 0 && Done%20 == 0)
|
|
if (Prog != 0 && Done%20 == 0)
|
|
@@ -619,7 +832,7 @@ void pkgDepCache::Update(OpProgress *Prog)
|
|
|
for (VerIterator V = I.VersionList(); V.end() != true; V++)
|
|
for (VerIterator V = I.VersionList(); V.end() != true; V++)
|
|
|
{
|
|
{
|
|
|
unsigned char Group = 0;
|
|
unsigned char Group = 0;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
for (DepIterator D = V.DependsList(); D.end() != true; D++)
|
|
for (DepIterator D = V.DependsList(); D.end() != true; D++)
|
|
|
{
|
|
{
|
|
|
// Build the dependency state.
|
|
// Build the dependency state.
|
|
@@ -637,21 +850,158 @@ void pkgDepCache::Update(OpProgress *Prog)
|
|
|
D->Type == Dep::DpkgBreaks ||
|
|
D->Type == Dep::DpkgBreaks ||
|
|
|
D->Type == Dep::Obsoletes)
|
|
D->Type == Dep::Obsoletes)
|
|
|
State = ~State;
|
|
State = ~State;
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Compute the pacakge dependency state and size additions
|
|
|
|
|
|
|
+ // Compute the package dependency state and size additions
|
|
|
AddSizes(I);
|
|
AddSizes(I);
|
|
|
UpdateVerState(I);
|
|
UpdateVerState(I);
|
|
|
AddStates(I);
|
|
AddStates(I);
|
|
|
|
|
+
|
|
|
|
|
+ if (checkMultiArch != true || I->CurrentVer == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ VerIterator const V = I.CurrentVer();
|
|
|
|
|
+ if (V->MultiArch != Version::All)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ recheck.insert(I.Index());
|
|
|
|
|
+ --Done; // no progress if we need to recheck the package
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (checkMultiArch == true) {
|
|
|
|
|
+ /* FIXME: recheck breaks proper progress reporting as we don't know
|
|
|
|
|
+ how many packages we need to recheck. To lower the effect
|
|
|
|
|
+ a bit we increase with a kill, but we should do something more clever… */
|
|
|
|
|
+ while(recheck.empty() == false)
|
|
|
|
|
+ for (std::set<unsigned long>::const_iterator p = recheck.begin();
|
|
|
|
|
+ p != recheck.end();) {
|
|
|
|
|
+ if (Prog != 0 && Done%20 == 0)
|
|
|
|
|
+ Prog->Progress(Done);
|
|
|
|
|
+ PkgIterator P = PkgIterator(*Cache, Cache->PkgP + *p);
|
|
|
|
|
+ if (RemovePseudoInstalledPkg(P, recheck) == true) {
|
|
|
|
|
+ ++killed;
|
|
|
|
|
+ ++Done;
|
|
|
|
|
+ }
|
|
|
|
|
+ recheck.erase(p++);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Okay, we have killed a great amount of pseudopackages -
|
|
|
|
|
+ we have killed so many that we have now arch "all" packages
|
|
|
|
|
+ without an installed pseudo package, but we NEED an installed
|
|
|
|
|
+ pseudo package, so we will search now for a pseudo package
|
|
|
|
|
+ we can install without breaking everything. */
|
|
|
|
|
+ for (GrpIterator G = Cache->GrpBegin(); G.end() != true; ++G)
|
|
|
|
|
+ {
|
|
|
|
|
+ PkgIterator P = G.FindPkg("all");
|
|
|
|
|
+ if (P.end() == true)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (P->CurrentVer == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ bool installed = false;
|
|
|
|
|
+ for (P = G.FindPkg("any"); P.end() != true; P = G.NextPkg(P))
|
|
|
|
|
+ {
|
|
|
|
|
+ if (strcmp(P.Arch(), "all") == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (P->CurrentVer == 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ installed = true;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (installed == false)
|
|
|
|
|
+ recheck.insert(G.Index());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ while (recheck.empty() != true)
|
|
|
|
|
+ {
|
|
|
|
|
+ std::set<unsigned long>::const_iterator g = recheck.begin();
|
|
|
|
|
+ unsigned long const G = *g;
|
|
|
|
|
+ recheck.erase(g);
|
|
|
|
|
+ if (unlikely(ReInstallPseudoForGroup(G, recheck) == false))
|
|
|
|
|
+ _error->Warning(_("Internal error, group '%s' has no installable pseudo package"), GrpIterator(*Cache, Cache->GrpP + G).Name());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (Prog != 0)
|
|
|
|
|
|
|
+ if (Prog != 0)
|
|
|
Prog->Progress(Done);
|
|
Prog->Progress(Done);
|
|
|
|
|
|
|
|
readStateFile(Prog);
|
|
readStateFile(Prog);
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
|
|
+// DepCache::ReInstallPseudoForGroup - MultiArch helper for Update() /*{{{*/
|
|
|
|
|
+// ---------------------------------------------------------------------
|
|
|
|
|
+/* RemovePseudoInstalledPkg() is very successful. It even kills packages
|
|
|
|
|
+ to an amount that no pseudo package is left, but we need a pseudo package
|
|
|
|
|
+ for upgrading senarios so we need to reinstall one pseudopackage which
|
|
|
|
|
+ doesn't break everything. Thankfully we can't have architecture depending
|
|
|
|
|
+ negative dependencies so this problem is already eliminated */
|
|
|
|
|
+bool pkgDepCache::ReInstallPseudoForGroup(pkgCache::PkgIterator const &P, std::set<unsigned long> &recheck)
|
|
|
|
|
+{
|
|
|
|
|
+ if (P->CurrentVer != 0)
|
|
|
|
|
+ return true;
|
|
|
|
|
+ // recursive call for packages which provide this package
|
|
|
|
|
+ for (pkgCache::PrvIterator Prv = P.ProvidesList(); Prv.end() != true; ++Prv)
|
|
|
|
|
+ ReInstallPseudoForGroup(Prv.OwnerPkg(), recheck);
|
|
|
|
|
+ // check if we actually need to look at this group
|
|
|
|
|
+ unsigned long const G = P->Group;
|
|
|
|
|
+ std::set<unsigned long>::const_iterator Pi = recheck.find(G);
|
|
|
|
|
+ if (Pi == recheck.end())
|
|
|
|
|
+ return true;
|
|
|
|
|
+ recheck.erase(Pi); // remove here, so we can't fall into an endless loop
|
|
|
|
|
+ if (unlikely(ReInstallPseudoForGroup(G, recheck) == false))
|
|
|
|
|
+ {
|
|
|
|
|
+ recheck.insert(G);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+bool pkgDepCache::ReInstallPseudoForGroup(unsigned long const &G, std::set<unsigned long> &recheck)
|
|
|
|
|
+{
|
|
|
|
|
+ std::vector<std::string> static const Archs = APT::Configuration::getArchitectures();
|
|
|
|
|
+ pkgCache::GrpIterator Grp(*Cache, Cache->GrpP + G);
|
|
|
|
|
+ if (unlikely(Grp.end() == true))
|
|
|
|
|
+ return false;
|
|
|
|
|
+ for (std::vector<std::string>::const_iterator a = Archs.begin();
|
|
|
|
|
+ a != Archs.end(); ++a)
|
|
|
|
|
+ {
|
|
|
|
|
+ pkgCache::PkgIterator P = Grp.FindPkg(*a);
|
|
|
|
|
+ if (P.end() == true)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ pkgCache::VerIterator allV = Grp.FindPkg("all").CurrentVer();
|
|
|
|
|
+ for (VerIterator V = P.VersionList(); V.end() != true; ++V)
|
|
|
|
|
+ {
|
|
|
|
|
+ // search for the same version as the all package
|
|
|
|
|
+ if (allV->Hash != V->Hash || strcmp(allV.VerStr(),V.VerStr()) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ unsigned char const CurDepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy);
|
|
|
|
|
+ // If it is broken, try to install dependencies first before retry
|
|
|
|
|
+ if ((CurDepState & DepInstMin) != DepInstMin)
|
|
|
|
|
+ {
|
|
|
|
|
+ for (pkgCache::DepIterator D = V.DependsList(); D.end() != true; ++D)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (D->Type != pkgCache::Dep::PreDepends && D->Type != pkgCache::Dep::Depends)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ ReInstallPseudoForGroup(D.TargetPkg(), recheck);
|
|
|
|
|
+ }
|
|
|
|
|
+ unsigned char const CurDepState = VersionState(V.DependsList(),DepInstall,DepInstMin,DepInstPolicy);
|
|
|
|
|
+ // if package ist still broken… try another arch
|
|
|
|
|
+ if ((CurDepState & DepInstMin) != DepInstMin)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ // dependencies satisfied: reinstall the package
|
|
|
|
|
+ RemoveSizes(P);
|
|
|
|
|
+ RemoveStates(P);
|
|
|
|
|
+ P->CurrentVer = V.Index();
|
|
|
|
|
+ PkgState[P->ID].InstallVer = V;
|
|
|
|
|
+ AddStates(P);
|
|
|
|
|
+ Update(P);
|
|
|
|
|
+ AddSizes(P);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+ /*}}}*/
|
|
|
// DepCache::Update - Update the deps list of a package /*{{{*/
|
|
// DepCache::Update - Update the deps list of a package /*{{{*/
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
|
/* This is a helper for update that only does the dep portion of the scan.
|
|
/* This is a helper for update that only does the dep portion of the scan.
|
|
@@ -813,6 +1163,10 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
|
|
|
AddStates(Pkg);
|
|
AddStates(Pkg);
|
|
|
Update(Pkg);
|
|
Update(Pkg);
|
|
|
AddSizes(Pkg);
|
|
AddSizes(Pkg);
|
|
|
|
|
+
|
|
|
|
|
+ // if we remove the pseudo package, we also need to remove the "real"
|
|
|
|
|
+ if (Pkg->CurrentVer != 0 && Pkg.CurrentVer().Pseudo() == true)
|
|
|
|
|
+ MarkDelete(Pkg.Group().FindPkg("all"), rPurge, Depth+1, FromUser);
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
// DepCache::IsDeleteOk - check if it is ok to remove this package /*{{{*/
|
|
// DepCache::IsDeleteOk - check if it is ok to remove this package /*{{{*/
|
|
@@ -901,6 +1255,10 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
|
|
|
Update(Pkg);
|
|
Update(Pkg);
|
|
|
AddSizes(Pkg);
|
|
AddSizes(Pkg);
|
|
|
|
|
|
|
|
|
|
+ // always trigger the install of the all package for a pseudo package
|
|
|
|
|
+ if (P.CandidateVerIter(*Cache).Pseudo() == true)
|
|
|
|
|
+ MarkInstall(Pkg.Group().FindPkg("all"), AutoInst, Depth, FromUser, ForceImportantDeps);
|
|
|
|
|
+
|
|
|
if (AutoInst == false)
|
|
if (AutoInst == false)
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
@@ -1099,6 +1457,9 @@ bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
|
|
|
/* */
|
|
/* */
|
|
|
void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
|
|
void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
|
|
|
{
|
|
{
|
|
|
|
|
+ if (unlikely(Pkg.end() == true))
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
ActionGroup group(*this);
|
|
ActionGroup group(*this);
|
|
|
|
|
|
|
|
RemoveSizes(Pkg);
|
|
RemoveSizes(Pkg);
|
|
@@ -1112,12 +1473,17 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
|
|
|
|
|
|
|
|
AddStates(Pkg);
|
|
AddStates(Pkg);
|
|
|
AddSizes(Pkg);
|
|
AddSizes(Pkg);
|
|
|
|
|
+
|
|
|
|
|
+ if (unlikely(Pkg.CurrentVer().end() == true) || Pkg.CurrentVer().Pseudo() == false)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ SetReInstall(Pkg.Group().FindPkg("all"), To);
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
|
|
// DepCache::SetCandidateVersion - Change the candidate version /*{{{*/
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
|
/* */
|
|
/* */
|
|
|
-void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
|
|
|
|
|
|
|
+void pkgDepCache::SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo)
|
|
|
{
|
|
{
|
|
|
ActionGroup group(*this);
|
|
ActionGroup group(*this);
|
|
|
|
|
|
|
@@ -1135,6 +1501,28 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
|
|
|
AddStates(Pkg);
|
|
AddStates(Pkg);
|
|
|
Update(Pkg);
|
|
Update(Pkg);
|
|
|
AddSizes(Pkg);
|
|
AddSizes(Pkg);
|
|
|
|
|
+
|
|
|
|
|
+ if (TargetVer.Pseudo() == false || Pseudo == false)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ // the version was pseudo: set all other pseudos also
|
|
|
|
|
+ pkgCache::GrpIterator Grp = Pkg.Group();
|
|
|
|
|
+ for (Pkg = Grp.FindPkg("any"); Pkg.end() == false; ++Pkg)
|
|
|
|
|
+ {
|
|
|
|
|
+ StateCache &P = PkgState[Pkg->ID];
|
|
|
|
|
+ if (TargetVer.SimilarVer(P.CandidateVerIter(*this)) == true ||
|
|
|
|
|
+ (P.CandidateVerIter(*this).Pseudo() == false &&
|
|
|
|
|
+ strcmp(Pkg.Arch(), "all") != 0))
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (TargetVer.SimilarVer(Ver) == false)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ SetCandidateVersion(Ver, false);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
|
|
void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
|
|
@@ -1197,7 +1585,7 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
|
/* The default just returns the highest available version that is not
|
|
/* The default just returns the highest available version that is not
|
|
|
a source and automatic. */
|
|
a source and automatic. */
|
|
|
-pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
|
|
|
|
|
|
|
+pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pkg)
|
|
|
{
|
|
{
|
|
|
/* Not source/not automatic versions cannot be a candidate version
|
|
/* Not source/not automatic versions cannot be a candidate version
|
|
|
unless they are already installed */
|
|
unless they are already installed */
|
|
@@ -1232,7 +1620,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
|
|
|
// Policy::IsImportantDep - True if the dependency is important /*{{{*/
|
|
// Policy::IsImportantDep - True if the dependency is important /*{{{*/
|
|
|
// ---------------------------------------------------------------------
|
|
// ---------------------------------------------------------------------
|
|
|
/* */
|
|
/* */
|
|
|
-bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
|
|
|
|
|
|
|
+bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep)
|
|
|
{
|
|
{
|
|
|
if(Dep.IsCritical())
|
|
if(Dep.IsCritical())
|
|
|
return true;
|
|
return true;
|
|
@@ -1251,54 +1639,6 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
|
|
|
else if(Dep->Type == pkgCache::Dep::Suggests)
|
|
else if(Dep->Type == pkgCache::Dep::Suggests)
|
|
|
return _config->FindB("APT::Install-Suggests", false);
|
|
return _config->FindB("APT::Install-Suggests", false);
|
|
|
|
|
|
|
|
- return false;
|
|
|
|
|
-}
|
|
|
|
|
- /*}}}*/
|
|
|
|
|
-pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc() /*{{{*/
|
|
|
|
|
- : constructedSuccessfully(false)
|
|
|
|
|
-{
|
|
|
|
|
- Configuration::Item const *Opts;
|
|
|
|
|
- Opts = _config->Tree("APT::NeverAutoRemove");
|
|
|
|
|
- if (Opts != 0 && Opts->Child != 0)
|
|
|
|
|
- {
|
|
|
|
|
- Opts = Opts->Child;
|
|
|
|
|
- for (; Opts != 0; Opts = Opts->Next)
|
|
|
|
|
- {
|
|
|
|
|
- if (Opts->Value.empty() == true)
|
|
|
|
|
- continue;
|
|
|
|
|
-
|
|
|
|
|
- regex_t *p = new regex_t;
|
|
|
|
|
- if(regcomp(p,Opts->Value.c_str(),
|
|
|
|
|
- REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
|
|
|
|
|
- {
|
|
|
|
|
- regfree(p);
|
|
|
|
|
- delete p;
|
|
|
|
|
- _error->Error("Regex compilation error for APT::NeverAutoRemove");
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- rootSetRegexp.push_back(p);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- constructedSuccessfully = true;
|
|
|
|
|
-}
|
|
|
|
|
- /*}}}*/
|
|
|
|
|
-pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc() /*{{{*/
|
|
|
|
|
-{
|
|
|
|
|
- for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
|
|
|
|
|
- {
|
|
|
|
|
- regfree(rootSetRegexp[i]);
|
|
|
|
|
- delete rootSetRegexp[i];
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
- /*}}}*/
|
|
|
|
|
-bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) /*{{{*/
|
|
|
|
|
-{
|
|
|
|
|
- for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
|
|
|
|
|
- if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
|
|
|
|
|
- return true;
|
|
|
|
|
-
|
|
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
@@ -1339,7 +1679,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
|
|
|
|
|
|
|
|
// debug output
|
|
// debug output
|
|
|
if(debug_autoremove && PkgState[p->ID].Flags & Flag::Auto)
|
|
if(debug_autoremove && PkgState[p->ID].Flags & Flag::Auto)
|
|
|
- std::clog << "AutoDep: " << p.Name() << std::endl;
|
|
|
|
|
|
|
+ std::clog << "AutoDep: " << p.FullName() << std::endl;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// init vars
|
|
// init vars
|
|
@@ -1353,8 +1693,11 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
|
|
|
{
|
|
{
|
|
|
if(!(PkgState[p->ID].Flags & Flag::Auto) ||
|
|
if(!(PkgState[p->ID].Flags & Flag::Auto) ||
|
|
|
(p->Flags & Flag::Essential) ||
|
|
(p->Flags & Flag::Essential) ||
|
|
|
- userFunc.InRootSet(p))
|
|
|
|
|
-
|
|
|
|
|
|
|
+ userFunc.InRootSet(p) ||
|
|
|
|
|
+ // be nice even then a required package violates the policy (#583517)
|
|
|
|
|
+ // and do the full mark process also for required packages
|
|
|
|
|
+ (p.CurrentVer().end() != true &&
|
|
|
|
|
+ p.CurrentVer()->Priority == pkgCache::State::Required))
|
|
|
{
|
|
{
|
|
|
// the package is installed (and set to keep)
|
|
// the package is installed (and set to keep)
|
|
|
if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
|
|
if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
|
|
@@ -1373,13 +1716,18 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
|
|
|
// MarkPackage - mark a single package in Mark-and-Sweep /*{{{*/
|
|
// MarkPackage - mark a single package in Mark-and-Sweep /*{{{*/
|
|
|
void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
|
const pkgCache::VerIterator &ver,
|
|
const pkgCache::VerIterator &ver,
|
|
|
- bool follow_recommends,
|
|
|
|
|
- bool follow_suggests)
|
|
|
|
|
|
|
+ bool const &follow_recommends,
|
|
|
|
|
+ bool const &follow_suggests)
|
|
|
{
|
|
{
|
|
|
pkgDepCache::StateCache &state = PkgState[pkg->ID];
|
|
pkgDepCache::StateCache &state = PkgState[pkg->ID];
|
|
|
- VerIterator currver = pkg.CurrentVer();
|
|
|
|
|
- VerIterator candver = state.CandidateVerIter(*this);
|
|
|
|
|
- VerIterator instver = state.InstVerIter(*this);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // if we are marked already we are done
|
|
|
|
|
+ if(state.Marked)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ VerIterator const currver = pkg.CurrentVer();
|
|
|
|
|
+ VerIterator const candver = state.CandidateVerIter(*this);
|
|
|
|
|
+ VerIterator const instver = state.InstVerIter(*this);
|
|
|
|
|
|
|
|
#if 0
|
|
#if 0
|
|
|
// If a package was garbage-collected but is now being marked, we
|
|
// If a package was garbage-collected but is now being marked, we
|
|
@@ -1405,15 +1753,11 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
|
!(ver == currver && instver.end() && !ver.end()))
|
|
!(ver == currver && instver.end() && !ver.end()))
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
- // if we are marked already we are done
|
|
|
|
|
- if(state.Marked)
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false);
|
|
|
|
|
|
|
|
- bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false);
|
|
|
|
|
-
|
|
|
|
|
if(debug_autoremove)
|
|
if(debug_autoremove)
|
|
|
{
|
|
{
|
|
|
- std::clog << "Marking: " << pkg.Name();
|
|
|
|
|
|
|
+ std::clog << "Marking: " << pkg.FullName();
|
|
|
if(!ver.end())
|
|
if(!ver.end())
|
|
|
std::clog << " " << ver.VerStr();
|
|
std::clog << " " << ver.VerStr();
|
|
|
if(!currver.end())
|
|
if(!currver.end())
|
|
@@ -1425,8 +1769,31 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
|
|
|
|
|
|
state.Marked=true;
|
|
state.Marked=true;
|
|
|
|
|
|
|
|
- if(!ver.end())
|
|
|
|
|
|
|
+ if(ver.end() == true)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ // If the version belongs to a Multi-Arch all package
|
|
|
|
|
+ // we will mark all others in this Group with this version also
|
|
|
|
|
+ if (ver->MultiArch == pkgCache::Version::All &&
|
|
|
|
|
+ strcmp(ver.Arch(true), "all") == 0)
|
|
|
{
|
|
{
|
|
|
|
|
+ GrpIterator G = pkg.Group();
|
|
|
|
|
+ const char* const VerStr = ver.VerStr();
|
|
|
|
|
+ for (PkgIterator P = G.FindPkg("any");
|
|
|
|
|
+ P.end() != true; P = G.NextPkg(P))
|
|
|
|
|
+ {
|
|
|
|
|
+ for (VerIterator V = P.VersionList();
|
|
|
|
|
+ V.end() != true; ++V)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (ver->Hash != V->Hash ||
|
|
|
|
|
+ strcmp(VerStr, V.VerStr()) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ MarkPackage(P, V, follow_recommends, follow_suggests);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
for(DepIterator d = ver.DependsList(); !d.end(); ++d)
|
|
for(DepIterator d = ver.DependsList(); !d.end(); ++d)
|
|
|
{
|
|
{
|
|
|
if(d->Type == Dep::Depends ||
|
|
if(d->Type == Dep::Depends ||
|
|
@@ -1444,10 +1811,9 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
|
{
|
|
{
|
|
|
if(debug_autoremove)
|
|
if(debug_autoremove)
|
|
|
{
|
|
{
|
|
|
- std::clog << "Following dep: " << d.ParentPkg().Name()
|
|
|
|
|
|
|
+ std::clog << "Following dep: " << d.ParentPkg().FullName()
|
|
|
<< " " << d.ParentVer().VerStr() << " "
|
|
<< " " << d.ParentVer().VerStr() << " "
|
|
|
- << d.DepType() << " "
|
|
|
|
|
- << d.TargetPkg().Name();
|
|
|
|
|
|
|
+ << d.DepType() << " " << d.TargetPkg().FullName();
|
|
|
if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
|
|
if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
|
|
|
{
|
|
{
|
|
|
std::clog << " (" << d.CompType() << " "
|
|
std::clog << " (" << d.CompType() << " "
|
|
@@ -1455,7 +1821,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
|
}
|
|
}
|
|
|
std::clog << std::endl;
|
|
std::clog << std::endl;
|
|
|
}
|
|
}
|
|
|
- MarkPackage(V.ParentPkg(), V,
|
|
|
|
|
|
|
+ MarkPackage(V.ParentPkg(), V,
|
|
|
follow_recommends, follow_suggests);
|
|
follow_recommends, follow_suggests);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1468,17 +1834,16 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
|
{
|
|
{
|
|
|
if(debug_autoremove)
|
|
if(debug_autoremove)
|
|
|
{
|
|
{
|
|
|
- std::clog << "Following dep: " << d.ParentPkg().Name()
|
|
|
|
|
- << " " << d.ParentVer().VerStr() << " "
|
|
|
|
|
- << d.DepType() << " "
|
|
|
|
|
- << d.TargetPkg().Name();
|
|
|
|
|
|
|
+ std::clog << "Following dep: " << d.ParentPkg().FullName() << " "
|
|
|
|
|
+ << d.ParentVer().VerStr() << " "
|
|
|
|
|
+ << d.DepType() << " " << d.TargetPkg().FullName() << " ";
|
|
|
if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
|
|
if((d->CompareOp & ~pkgCache::Dep::Or) != pkgCache::Dep::NoOp)
|
|
|
{
|
|
{
|
|
|
std::clog << " (" << d.CompType() << " "
|
|
std::clog << " (" << d.CompType() << " "
|
|
|
<< d.TargetVer() << ")";
|
|
<< d.TargetVer() << ")";
|
|
|
}
|
|
}
|
|
|
std::clog << ", provided by "
|
|
std::clog << ", provided by "
|
|
|
- << prv.OwnerPkg().Name() << " "
|
|
|
|
|
|
|
+ << prv.OwnerPkg().FullName() << " "
|
|
|
<< prv.OwnerVer().VerStr()
|
|
<< prv.OwnerVer().VerStr()
|
|
|
<< std::endl;
|
|
<< std::endl;
|
|
|
}
|
|
}
|
|
@@ -1489,7 +1854,6 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
/*}}}*/
|
|
/*}}}*/
|
|
|
bool pkgDepCache::Sweep() /*{{{*/
|
|
bool pkgDepCache::Sweep() /*{{{*/
|
|
@@ -1511,7 +1875,7 @@ bool pkgDepCache::Sweep() /*{{{*/
|
|
|
{
|
|
{
|
|
|
state.Garbage=true;
|
|
state.Garbage=true;
|
|
|
if(debug_autoremove)
|
|
if(debug_autoremove)
|
|
|
- std::clog << "Garbage: " << p.Name() << std::endl;
|
|
|
|
|
|
|
+ std::clog << "Garbage: " << p.FullName() << std::endl;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|