// Include Files /*{{{*/
#include <config.h>
+#include <apt-pkg/algorithms.h>
#include <apt-pkg/error.h>
#include <apt-pkg/cacheset.h>
#include <apt-pkg/depcache.h>
static bool SkipUnavailableVersions(pkgDepCache &Cache, pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver)/*{{{*/
{
/* versions which aren't current and aren't available in
- any "online" source file are bad, expect if they are the choosen
+ any "online" source file are bad, expect if they are the chosen
candidate: The exception is for build-dep implementation as it creates
such pseudo (package) versions and removes them later on again.
We filter out versions at all so packages in 'rc' state only available
Progress->Progress(p);
}
}
- return true;
+ return Okay;
}
/*}}}*/
// EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/
}
continue;
} else if (section.Exists("Error") == true) {
+ if (_error->PendingError()) {
+ if (Progress != nullptr)
+ Progress->Done();
+ Progress = nullptr;
+ _error->DumpErrors(std::cerr, GlobalError::DEBUG, false);
+ }
std::string msg = SubstVar(SubstVar(section.FindS("Message"), "\n .\n", "\n\n"), "\n ", "\n");
if (msg.empty() == true) {
msg = _("External solver failed without a proper error message");
_error->Error("%s", msg.c_str());
} else
_error->Error("External solver failed with: %s", msg.substr(0,msg.find('\n')).c_str());
- if (Progress != NULL)
+ if (Progress != nullptr)
Progress->Done();
std::cerr << "The solver encountered an error of type: " << section.FindS("Error") << std::endl;
std::cerr << "The following information might help you to understand what is wrong:" << std::endl;
/*}}}*/
// EDSP::WriteProgess - pulse to the given file descriptor /*{{{*/
bool EDSP::WriteProgress(unsigned short const percent, const char* const message, FILE* output) {
- fprintf(output, "Progress: %s\n", TimeRFC1123(time(NULL)).c_str());
+ fprintf(output, "Progress: %s\n", TimeRFC1123(time(NULL), true).c_str());
fprintf(output, "Percentage: %d\n", percent);
fprintf(output, "Message: %s\n\n", message);
fflush(output);
return true;
}
bool EDSP::WriteProgress(unsigned short const percent, const char* const message, FileFd &output) {
- return WriteOkay(output, "Progress: ", TimeRFC1123(time(NULL)), "\n",
+ return WriteOkay(output, "Progress: ", TimeRFC1123(time(NULL), true), "\n",
"Percentage: ", percent, "\n",
"Message: ", message, "\n\n") && output.Flush();
}
return true;
}
/*}}}*/
+static bool CreateDumpFile(char const * const id, char const * const type, FileFd &output)/*{{{*/
+{
+ auto const dumpfile = _config->FindFile((std::string("Dir::Log::") + type).c_str());
+ if (dumpfile.empty())
+ return false;
+ auto const dumpdir = flNotFile(dumpfile);
+ _error->PushToStack();
+ bool errored_out = CreateAPTDirectoryIfNeeded(dumpdir, dumpdir) == false ||
+ output.Open(dumpfile, FileFd::WriteOnly | FileFd::Exclusive | FileFd::Create, FileFd::Extension, 0644) == false;
+ std::vector<std::string> downgrademsgs;
+ while (_error->empty() == false)
+ {
+ std::string msg;
+ _error->PopMessage(msg);
+ downgrademsgs.emplace_back(std::move(msg));
+ }
+ _error->RevertToStack();
+ for (auto && msg : downgrademsgs)
+ _error->Warning("%s", msg.c_str());
+ if (errored_out)
+ return _error->WarningE(id, _("Could not open file '%s'"), dumpfile.c_str());
+ return true;
+}
+ /*}}}*/
// EDSP::ResolveExternal - resolve problems by asking external for help {{{*/
bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
unsigned int const flags, OpProgress *Progress) {
if (strcmp(solver, "internal") == 0)
{
- auto const dumpfile = _config->FindFile("Dir::Log::Solver");
- if (dumpfile.empty())
- return false;
- auto const dumpdir = flNotFile(dumpfile);
FileFd output;
- if (CreateAPTDirectoryIfNeeded(dumpdir, dumpdir) == false ||
- output.Open(dumpfile, FileFd::WriteOnly | FileFd::Exclusive | FileFd::Create, FileFd::Extension, 0644) == false)
- return _error->WarningE("EDSP::Resolve", _("Could not open file '%s'"), dumpfile.c_str());
- bool Okay = EDSP::WriteRequest(Cache, output, flags, nullptr);
+ bool Okay = CreateDumpFile("EDSP::Resolve", "solver", output);
+ Okay &= EDSP::WriteRequest(Cache, output, flags, nullptr);
return Okay && EDSP::WriteScenario(Cache, output, nullptr);
}
+ _error->PushToStack();
int solver_in, solver_out;
- pid_t const solver_pid = EDSP::ExecuteSolver(solver, &solver_in, &solver_out, true);
+ pid_t const solver_pid = ExecuteSolver(solver, &solver_in, &solver_out, true);
if (solver_pid == 0)
return false;
return _error->Errno("ResolveExternal", "Opening solver %s stdin on fd %d for writing failed", solver, solver_in);
bool Okay = output.Failed() == false;
- if (Progress != NULL)
+ if (Okay && Progress != NULL)
Progress->OverallProgress(0, 100, 5, _("Execute external solver"));
Okay &= EDSP::WriteRequest(Cache, output, flags, Progress);
- if (Progress != NULL)
+ if (Okay && Progress != NULL)
Progress->OverallProgress(5, 100, 20, _("Execute external solver"));
Okay &= EDSP::WriteScenario(Cache, output, Progress);
output.Close();
- if (Progress != NULL)
+ if (Okay && Progress != NULL)
Progress->OverallProgress(25, 100, 75, _("Execute external solver"));
- if (Okay && EDSP::ReadResponse(solver_out, Cache, Progress) == false)
- return false;
-
- return ExecWait(solver_pid, solver);
+ bool const ret = EDSP::ReadResponse(solver_out, Cache, Progress);
+ _error->MergeWithStack();
+ if (ExecWait(solver_pid, solver))
+ return ret;
+ return false;
}
bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
bool const upgrade, bool const distUpgrade,
bool EIPP::OrderInstall(char const * const solver, pkgPackageManager * const PM, /*{{{*/
unsigned int const flags, OpProgress * const Progress)
{
+ if (strcmp(solver, "internal") == 0)
+ {
+ FileFd output;
+ _error->PushToStack();
+ bool Okay = CreateDumpFile("EIPP::OrderInstall", "planner", output);
+ if (Okay == false && dynamic_cast<pkgSimulate*>(PM) != nullptr)
+ {
+ _error->RevertToStack();
+ return false;
+ }
+ _error->MergeWithStack();
+ Okay &= EIPP::WriteRequest(PM->Cache, output, flags, nullptr);
+ return Okay && EIPP::WriteScenario(PM->Cache, output, nullptr);
+ }
+ _error->PushToStack();
int solver_in, solver_out;
- pid_t const solver_pid = ExecuteExternal("planer", solver, "Dir::Bin::Planers", &solver_in, &solver_out);
+ pid_t const solver_pid = ExecuteExternal("planner", solver, "Dir::Bin::Planners", &solver_in, &solver_out);
if (solver_pid == 0)
return false;
FileFd output;
if (output.OpenDescriptor(solver_in, FileFd::WriteOnly | FileFd::BufferedWrite, true) == false)
- return _error->Errno("OrderInstall", "Opening planer %s stdin on fd %d for writing failed", solver, solver_in);
+ return _error->Errno("EIPP::OrderInstall", "Opening planner %s stdin on fd %d for writing failed", solver, solver_in);
bool Okay = output.Failed() == false;
- if (Progress != NULL)
- Progress->OverallProgress(0, 100, 5, _("Execute external planer"));
+ if (Okay && Progress != NULL)
+ Progress->OverallProgress(0, 100, 5, _("Execute external planner"));
Okay &= EIPP::WriteRequest(PM->Cache, output, flags, Progress);
- if (Progress != NULL)
- Progress->OverallProgress(5, 100, 20, _("Execute external planer"));
+ if (Okay && Progress != NULL)
+ Progress->OverallProgress(5, 100, 20, _("Execute external planner"));
Okay &= EIPP::WriteScenario(PM->Cache, output, Progress);
output.Close();
- if (Progress != NULL)
- Progress->OverallProgress(25, 100, 75, _("Execute external planer"));
- if (Okay && EIPP::ReadResponse(solver_out, PM, Progress) == false)
- return false;
+ if (Okay)
+ {
+ if (Progress != nullptr)
+ Progress->OverallProgress(25, 100, 75, _("Execute external planner"));
- return ExecWait(solver_pid, solver);
+ // we don't tell the external planners about boring things
+ for (auto Pkg = PM->Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
+ {
+ if (Pkg->CurrentState == pkgCache::State::ConfigFiles && PM->Cache[Pkg].Purge() == true)
+ PM->Remove(Pkg, true);
+ }
+ }
+ bool const ret = EIPP::ReadResponse(solver_out, PM, Progress);
+ _error->MergeWithStack();
+ if (ExecWait(solver_pid, solver))
+ return ret;
+ return false;
}
/*}}}*/
bool EIPP::WriteRequest(pkgDepCache &Cache, FileFd &output, /*{{{*/
unsigned int const flags,
OpProgress * const Progress)
{
- (void)(flags);
if (Progress != NULL)
- Progress->SubProgress(Cache.Head().PackageCount, _("Send request to planer"));
+ Progress->SubProgress(Cache.Head().PackageCount, _("Send request to planner"));
unsigned long p = 0;
- string del, purge, inst, reinst;
+ string del, inst, reinst;
for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg, ++p)
{
if (Progress != NULL && p % 100 == 0)
Progress->Progress(p);
string* req;
pkgDepCache::StateCache &P = Cache[Pkg];
- if (P.Purge() == true)
- req = &purge;
+ if (P.Purge() == true && Pkg->CurrentState == pkgCache::State::ConfigFiles)
+ continue;
if (P.Delete() == true)
req = &del;
else if (P.NewInstall() == true || P.Upgrade() == true || P.Downgrade() == true)
WriteOkay(Okay, output, " ", *a);
WriteOkay(Okay, output, "\n");
- if (purge.empty() == false)
- WriteOkay(Okay, output, "Purge:", purge, "\n");
if (del.empty() == false)
WriteOkay(Okay, output, "Remove:", del, "\n");
if (inst.empty() == false)
WriteOkay(Okay, output, "Install:", inst, "\n");
if (reinst.empty() == false)
WriteOkay(Okay, output, "ReInstall:", reinst, "\n");
- WriteOkay(Okay, output, "Planer: ", _config->Find("APT::Planer", "internal"), "\n");
+ WriteOkay(Okay, output, "Planner: ", _config->Find("APT::Planner", "internal"), "\n");
+ if ((flags & Request::IMMEDIATE_CONFIGURATION_ALL) != 0)
+ WriteOkay(Okay, output, "Immediate-Configuration: yes\n");
+ else if ((flags & Request::NO_IMMEDIATE_CONFIGURATION) != 0)
+ WriteOkay(Okay, output, "Immediate-Configuration: no\n");
+ else if ((flags & Request::ALLOW_TEMPORARY_REMOVE_OF_ESSENTIALS) != 0)
+ WriteOkay(Okay, output, "Allow-Temporary-Remove-of-Essentials: yes\n");
return WriteOkay(Okay, output, "\n");
}
/*}}}*/
bool EIPP::WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress * const Progress)
{
if (Progress != NULL)
- Progress->SubProgress(Cache.Head().PackageCount, _("Send scenario to planer"));
+ Progress->SubProgress(Cache.Head().PackageCount, _("Send scenario to planner"));
unsigned long p = 0;
bool Okay = output.Failed() == false;
std::vector<std::string> archs = APT::Configuration::getArchitectures();
pkgset[PV->ID] = true;
}
pkgset[P->ID] = true;
+ if (strcmp(P.Arch(), "any") == 0)
+ {
+ APT::StringView const pkgname(P.Name());
+ auto const idxColon = pkgname.find(':');
+ if (idxColon != APT::StringView::npos)
+ {
+ pkgCache::PkgIterator PA;
+ if (pkgname.substr(idxColon + 1) == "any")
+ {
+ auto const GA = Cache.FindGrp(pkgname.substr(0, idxColon).to_string());
+ for (auto PA = GA.PackageList(); PA.end() == false; PA = GA.NextPkg(PA))
+ {
+ pkgset[PA->ID] = true;
+ }
+ }
+ else
+ {
+ auto const PA = Cache.FindPkg(pkgname.to_string());
+ if (PA.end() == false)
+ pkgset[PA->ID] = true;
+ }
+ }
+ }
+ else
+ {
+ auto const PA = Cache.FindPkg(P.FullName(false), "any");
+ if (PA.end() == false)
+ pkgset[PA->ID] = true;
+ }
}
};
for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
continue;
forAllInterestingVersions(Cache, Pkg, WriteVersion);
}
- return true;
+ return Okay;
}
/*}}}*/
// EIPP::ReadResponse - from the given file descriptor /*{{{*/
}
continue;
} else if (section.Exists("Error") == true) {
+ if (_error->PendingError()) {
+ if (Progress != nullptr)
+ Progress->Done();
+ Progress = nullptr;
+ _error->DumpErrors(std::cerr, GlobalError::DEBUG, false);
+ }
std::string msg = SubstVar(SubstVar(section.FindS("Message"), "\n .\n", "\n\n"), "\n ", "\n");
if (msg.empty() == true) {
- msg = _("External planer failed without a proper error message");
+ msg = _("External planner failed without a proper error message");
_error->Error("%s", msg.c_str());
} else
- _error->Error("External planer failed with: %s", msg.substr(0,msg.find('\n')).c_str());
- if (Progress != NULL)
+ _error->Error("External planner failed with: %s", msg.substr(0,msg.find('\n')).c_str());
+ if (Progress != nullptr)
Progress->Done();
- std::cerr << "The planer encountered an error of type: " << section.FindS("Error") << std::endl;
+ std::cerr << "The planner encountered an error of type: " << section.FindS("Error") << std::endl;
std::cerr << "The following information might help you to understand what is wrong:" << std::endl;
std::cerr << msg << std::endl << std::endl;
return false;
- } else if (section.Exists("Install") == true)
- type = "Install";
+ } else if (section.Exists("Unpack") == true)
+ type = "Unpack";
else if (section.Exists("Configure") == true)
type = "Configure";
else if (section.Exists("Remove") == true)
pkgCache::VerIterator Ver(PM->Cache.GetCache(), PM->Cache.GetCache().VerP + VerIdx[id]);
auto const Pkg = Ver.ParentPkg();
- if (strcmp(type, "Install") == 0)
+ if (strcmp(type, "Unpack") == 0)
PM->Install(Pkg, PM->FileNames[Pkg->ID]);
else if (strcmp(type, "Configure") == 0)
PM->Configure(Pkg);
else if (strcmp(type, "Remove") == 0)
PM->Remove(Pkg, PM->Cache[Pkg].Purge());
}
- return true;
+ return in.Failed() == false;
}
/*}}}*/
bool EIPP::ReadRequest(int const input, std::list<std::pair<std::string,PKG_ACTION>> &actions,/*{{{*/
_config->Set("APT::Architecture", line);
else if (LineStartsWithAndStrip(line, "Architectures:"))
_config->Set("APT::Architectures", SubstVar(line, " ", ","));
- else if (LineStartsWithAndStrip(line, "Planer:"))
+ else if (LineStartsWithAndStrip(line, "Planner:"))
; // purely informational line
+ else if (LineStartsWithAndStrip(line, "Immediate-Configuration:"))
+ {
+ if (localStringToBool(line, true))
+ flags |= Request::IMMEDIATE_CONFIGURATION_ALL;
+ else
+ flags |= Request::NO_IMMEDIATE_CONFIGURATION;
+ }
+ else if (ReadFlag(flags, line, "Allow-Temporary-Remove-of-Essentials:", Request::ALLOW_TEMPORARY_REMOVE_OF_ESSENTIALS))
+ ;
else
_error->Warning("Unknown line in EIPP Request stanza: %s", line.c_str());
}
}
return false;
-
-
- return false;
}
/*}}}*/
bool EIPP::ApplyRequest(std::list<std::pair<std::string,PKG_ACTION>> &actions,/*{{{*/