Skip to content

Commit

Permalink
API for solving solver problems
Browse files Browse the repository at this point in the history
  • Loading branch information
lslezak committed Jan 15, 2024
1 parent 8bbf2dc commit d8c5551
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ jobs:
- name: Smoke Test Preparation
run: sh smoke_test_prepare.sh

- name: Dump packages
run: zypper se

- name: Smoke Test Run
run: ruby smoke_test_run.rb
154 changes: 154 additions & 0 deletions src/Package.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,160 @@ PkgFunctions::PkgSolveErrors()
return YCPVoid();
}

/**
@builtin PkgSolveProblems
@short Returns number of fails
@description
only valid after a call of PkgSolve/PkgSolveCheckTargetOnly that returned false
return number of fails
@return integer
@example
```
[
{
"description" => "the to be installed yast2-theme-SLE-4.5.0-lp154.2.1.noarch " \
"conflicts with 'namespace:otherproviders(yast2-branding)' provided by the " \
"installed yast2-theme-5.0.1-lp154.2.1.noarch",
"details" => "",
"solutions" =>
[
{
"description" => "Following actions will be done:",
"details" =>
"deinstallation of yast2-theme-5.0.1-lp154.2.1.noarch\n" +
"deinstallation of yast2-theme-oxygen-5.0.1-lp154.2.1.noarch\n" +
"deinstallation of yast2-theme-breeze-5.0.1-lp154.2.1.noarch"
},
{
"description" => "do not install yast2-theme-SLE-4.5.0-lp154.2.1.noarch",
"details" => ""
}
]
}
]
```
*/
YCPValue
PkgFunctions::PkgSolveProblems()
{
YCPList ret;
auto problems = zypp_ptr()->resolver()->problems();
for_( problem, problems.begin(), problems.end() )
{
YCPMap problem_item;
problem_item->add(YCPString("description"), YCPString((*problem)->description()));
problem_item->add(YCPString("details"), YCPString((*problem)->details()));

YCPList solutions;
for_( solution, (*problem)->solutions().begin(), (*problem)->solutions().end() )
{
YCPMap solution_item;
solution_item->add(YCPString("description"), YCPString((*solution)->description()));
solution_item->add(YCPString("details"), YCPString((*solution)->details()));

solutions->add(solution_item);
}
problem_item->add(YCPString("solutions"), solutions);

ret->add(problem_item);
}
return ret;
}

/**
* @builtin PkgSetSolveSolutions
* You need to run the solver after applying the solutions.
* @param solutions List of applied solutions
* @return YCPValue
*/
YCPValue
PkgFunctions::PkgSetSolveSolutions(const YCPList& solutions)
{
y2milestone("Requested %d solutions", solutions->size());

zypp::ProblemSolutionList user_solutions;
bool error = false;
for (int index = 0; index < solutions->size(); index++ )
{
if (solutions->value(index).isNull() || !solutions->value(index)->isMap())
{
y2error("Pkg::PkgSetSolveSolutions: entry not a map at index %d", index);
error = true;
continue;
}

YCPMap solution = solutions->value(index)->asMap();

// check missing keys
if (solution->value(YCPString("description")).isNull()
|| solution->value(YCPString("details")).isNull()
|| solution->value(YCPString("solution_description")).isNull()
|| solution->value(YCPString("solution_details")).isNull())
{
y2error("Pkg::PkgSetSolveSolutions: missing required map key at index %d", index);
error = true;
continue;
}

// check string keys
if (!solution->value(YCPString("description"))->isString()
|| !solution->value(YCPString("details"))->isString()
|| !solution->value(YCPString("solution_description"))->isString()
|| !solution->value(YCPString("solution_details"))->isString())
{
y2error("Pkg::PkgSetSolveSolutions: non-string map value at index %d", index);
error = true;
continue;
}

// get the keys
std::string problem_description = solution->value(YCPString("description"))->asString()->value();
std::string problem_details = solution->value(YCPString("details"))->asString()->value();
std::string solution_description = solution->value(YCPString("solution_description"))->asString()->value();
std::string solution_details = solution->value(YCPString("solution_details"))->asString()->value();

auto problems = zypp_ptr()->resolver()->problems();
bool found = false;
for_( problem, problems.begin(), problems.end() )
{
// find the problem
if ((*problem)->description() == problem_description && (*problem)->details() == problem_details)
{
for_( solution, (*problem)->solutions().begin(), (*problem)->solutions().end() )
{
// find the solution
if ((*solution)->description() == solution_description && (*solution)->details() == solution_details)
{
// remember the found solution
user_solutions.push_back(*solution);
found = true;
break;
}
}
break;
}
}

// the specified solution was not found
if (!found) error = true;
}

y2milestone("Applying %ld solutions", user_solutions.size());
zypp::getZYpp()->resolver()->applySolutions(user_solutions);

return YCPBoolean(!error);
}


YCPValue
PkgFunctions::PkgResetSolveSolutions()
{
zypp::getZYpp()->resolver()->undo();
return YCPVoid();
}

namespace
{
///////////////////////////////////////////////////////////////////
Expand Down
6 changes: 6 additions & 0 deletions src/PkgFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,12 @@ class PkgFunctions
YCPBoolean PkgSolveCheckTargetOnly ();
/* TYPEINFO: integer()*/
YCPValue PkgSolveErrors ();
/* TYPEINFO: list<map<string,any>>()*/
YCPValue PkgSolveProblems ();
/* TYPEINFO: boolean(list<map<string,any>>)*/
YCPValue PkgSetSolveSolutions (const YCPList& solutions);
/* TYPEINFO: void()*/
YCPValue PkgResetSolveSolutions ();
YCPValue CommitHelper(const zypp::ZYppCommitPolicy *policy);
/* TYPEINFO: list<any>(integer)*/
YCPValue PkgCommit (const YCPInteger& medianr);
Expand Down

0 comments on commit d8c5551

Please sign in to comment.