X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/ee8c790a660a817417267379bca1a26e7813dfde..c31c1dded85ee1e88231a041aac7e507f2ed426c:/apt-pkg/edsp.cc?ds=sidebyside

diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc
index ce9ad250c..4d2230613 100644
--- a/apt-pkg/edsp.cc
+++ b/apt-pkg/edsp.cc
@@ -26,29 +26,42 @@ const char * const EDSP::DepMap[] = {"", "Depends", "Pre-Depends", "Suggests",
 				     "Obsoletes", "Breaks", "Enhances"};
 
 // EDSP::WriteScenario - to the given file descriptor			/*{{{*/
-bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output)
+bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
 {
+   if (Progress != NULL)
+      Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
+   unsigned long p = 0;
    for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
-      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
+      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p)
       {
 	 WriteScenarioVersion(Cache, output, Pkg, Ver);
 	 WriteScenarioDependency(Cache, output, Pkg, Ver);
 	 fprintf(output, "\n");
+	 if (Progress != NULL && p % 100 == 0)
+	    Progress->Progress(p);
       }
    return true;
 }
 									/*}}}*/
 // EDSP::WriteLimitedScenario - to the given file descriptor		/*{{{*/
 bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output,
-				APT::PackageSet const &pkgset)
+				APT::PackageSet const &pkgset,
+				OpProgress *Progress)
 {
-   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   if (Progress != NULL)
+      Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
+   unsigned long p  = 0;
+   for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p)
       for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
       {
 	 WriteScenarioVersion(Cache, output, Pkg, Ver);
 	 WriteScenarioLimitedDependency(Cache, output, Pkg, Ver, pkgset);
 	 fprintf(output, "\n");
+	 if (Progress != NULL && p % 100 == 0)
+	    Progress->Progress(p);
       }
+   if (Progress != NULL)
+      Progress->Done();
    return true;
 }
 									/*}}}*/
@@ -69,11 +82,11 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI
    if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
       fprintf(output, "Essential: yes\n");
    fprintf(output, "Section: %s\n", Ver.Section());
-   if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed)
+   if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
       fprintf(output, "Multi-Arch: allowed\n");
-   else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign)
+   else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
       fprintf(output, "Multi-Arch: foreign\n");
-   else if (Ver->MultiArch == pkgCache::Version::Same)
+   else if ((Ver->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
       fprintf(output, "Multi-Arch: same\n");
    signed short Pin = std::numeric_limits<signed short>::min();
    for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) {
@@ -184,11 +197,17 @@ void EDSP::WriteScenarioLimitedDependency(pkgDepCache &Cache, FILE* output,
 									/*}}}*/
 // EDSP::WriteRequest - to the given file descriptor			/*{{{*/
 bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade,
-			bool const DistUpgrade, bool const AutoRemove)
+			bool const DistUpgrade, bool const AutoRemove,
+			OpProgress *Progress)
 {
+   if (Progress != NULL)
+      Progress->SubProgress(Cache.Head().PackageCount, _("Send request to solver"));
+   unsigned long p = 0;
    string del, inst;
-   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
+   for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg, ++p)
    {
+      if (Progress != NULL && p % 100 == 0)
+         Progress->Progress(p);
       string* req;
       if (Cache[Pkg].Delete() == true)
 	 req = &del;
@@ -212,7 +231,7 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade,
    if (_config->FindB("APT::Solver::Strict-Pinning", true) == false)
       fprintf(output, "Strict-Pinning: no\n");
    string solverpref("APT::Solver::");
-   solverpref.append(_config->Find("APT::Solver::Name", "internal")).append("::Preferences");
+   solverpref.append(_config->Find("APT::Solver", "internal")).append("::Preferences");
    if (_config->Exists(solverpref) == true)
       fprintf(output, "Preferences: %s\n", _config->Find(solverpref,"").c_str());
    fprintf(output, "\n");
@@ -221,7 +240,7 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade,
 }
 									/*}}}*/
 // EDSP::ReadResponse - from the given file descriptor			/*{{{*/
-bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) {
+bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress) {
 	/* We build an map id to mmap offset here
 	   In theory we could use the offset as ID, but then VersionCount
 	   couldn't be used to create other versionmappings anymore and it
@@ -247,15 +266,26 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) {
 		else if (section.Exists("Remove") == true)
 			type = "Remove";
 		else if (section.Exists("Progress") == true) {
-			std::clog << TimeRFC1123(time(NULL)) << " ";
-			ioprintf(std::clog, "[ %3d%% ] ", section.FindI("Percentage", 0));
-			std::clog << section.FindS("Progress") << " - ";
-			string const msg = section.FindS("Message");
-			if (msg.empty() == true)
-				std::clog << "Solver is still working on the solution" << std::endl;
-			else
-				std::clog << msg << std::endl;
+			if (Progress != NULL) {
+				string msg = section.FindS("Message");
+				if (msg.empty() == true)
+					msg = _("Prepare for receiving solution");
+				Progress->SubProgress(100, msg, section.FindI("Percentage", 0));
+			}
 			continue;
+		} else if (section.Exists("Error") == true) {
+			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(msg.c_str());
+			} else
+				_error->Error("External solver failed with: %s", msg.substr(0,msg.find('\n')).c_str());
+			if (Progress != NULL)
+				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;
+			std::cerr << msg << std::endl << std::endl;
+			return false;
 		} else if (section.Exists("Autoremove") == true)
 			type = "Autoremove";
 		else
@@ -273,7 +303,7 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) {
 		pkgCache::VerIterator Ver(Cache.GetCache(), Cache.GetCache().VerP + VerIdx[id]);
 		Cache.SetCandidateVersion(Ver);
 		if (type == "Install")
-			Cache.MarkInstall(Ver.ParentPkg(), false, false);
+			Cache.MarkInstall(Ver.ParentPkg(), false, 0, false);
 		else if (type == "Remove")
 			Cache.MarkDelete(Ver.ParentPkg(), false);
 		else if (type == "Autoremove") {
@@ -457,8 +487,13 @@ bool EDSP::WriteProgress(unsigned short const percent, const char* const message
 	return true;
 }
 									/*}}}*/
-bool EDSP::WriteError(std::string const &message, FILE* output) { return false; }
-
+// EDSP::WriteError - format an error message to be send to file descriptor /*{{{*/
+bool EDSP::WriteError(char const * const uuid, std::string const &message, FILE* output) {
+	fprintf(output, "Error: %s\n", uuid);
+	fprintf(output, "Message: %s\n\n", SubstVar(SubstVar(message, "\n\n", "\n.\n"), "\n", "\n ").c_str());
+	return true;
+}
+									/*}}}*/
 // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes	{{{*/
 bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) {
 	std::vector<std::string> const solverDirs = _config->FindVector("Dir::Bin::Solvers");
@@ -502,7 +537,7 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o
 // EDSP::ResolveExternal - resolve problems by asking external for help	{{{*/
 bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
 			 bool const upgrade, bool const distUpgrade,
-			 bool const autoRemove) {
+			 bool const autoRemove, OpProgress *Progress) {
 	int solver_in, solver_out;
 	if (EDSP::ExecuteSolver(solver, &solver_in, &solver_out) == false)
 		return false;
@@ -510,12 +545,19 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
 	FILE* output = fdopen(solver_in, "w");
 	if (output == NULL)
 		return _error->Errno("Resolve", "fdopen on solver stdin failed");
-	EDSP::WriteRequest(Cache, output, upgrade, distUpgrade, autoRemove);
-	EDSP::WriteScenario(Cache, output);
+
+	if (Progress != NULL)
+		Progress->OverallProgress(0, 100, 5, _("Execute external solver"));
+	EDSP::WriteRequest(Cache, output, upgrade, distUpgrade, autoRemove, Progress);
+	if (Progress != NULL)
+		Progress->OverallProgress(5, 100, 20, _("Execute external solver"));
+	EDSP::WriteScenario(Cache, output, Progress);
 	fclose(output);
 
-	if (EDSP::ReadResponse(solver_out, Cache) == false)
-		return _error->Error("Reading solver response failed");
+	if (Progress != NULL)
+		Progress->OverallProgress(25, 100, 75, _("Execute external solver"));
+	if (EDSP::ReadResponse(solver_out, Cache, Progress) == false)
+		return false;
 
 	return true;
 }