[zypp-devel] excluding one package in a pattern in libzypp
Hi list, I am trying to create a chroot with libzypp, and I found when I need to remove a package and this package is part of a pattern which will be installed, the dependencies of the package will stay there. For example, if 'A' and 'C' are in a pattern 'base', and 'A' requires 'B', 'C' requires 'D', I need to install pattern 'base', also I need to set 'A' uninstalled, but I end up having 'B', 'C', 'D' in my chroot. If I am not installing 'A', I definitely needn't 'B' installed. Is there any comment? should I file a bug? (attached is the repository including pattern file and rpm files) Thanks Gui
On Wednesday 17 July 2013 09:15:13 Chen, Gui wrote:
Hi list,
I am trying to create a chroot with libzypp, and I found when I need to remove a package and this package is part of a pattern which will be installed, the dependencies of the package will stay there. For example, if 'A' and 'C' are in a pattern 'base', and 'A' requires 'B', 'C' requires 'D', I need to install pattern 'base', also I need to set 'A' uninstalled, but I end up having 'B', 'C', 'D' in my chroot. If I am not installing 'A', I definitely needn't 'B' installed. Is there any comment? should I file a bug?
How did you do it? You can't 'install pattern:base' and 'remove A' in one step, because 'pattern:base requires A': 'select pattern:base' 'deselect A' 'resolve pool' (fails: pattern:base requires A') What you describe could be created this way: 'select pattern:base' 'resolve pool' (will select A C, B, D) 'deselect A' Here 'D' is still selected, but just because 'resolve pool' was not called after changing the selection. However, if a 'resolve pool' fails, the Resolver provides list of 'Resolver::problems()'. Each Problem usually has a list of solutions(). A ProblemSolution can be applied to the resolver. Problem 1: ==================================== pattern:base requires A, but this requirement cannot be provided ------------------------------------ Solutions for problem #1: ==================================== do not ask to delete all solvables providing A ------------------------------------ do not ask to install a solvable providing pattern:base ------------------------------------ ==> ignore some dependencies of pattern:base ------------------------------------ If I apply the last solution, then resolve again, I get C and D selected. -- cu, Michael Andres +------------------------------------------------------------------+ Key fingerprint = 2DFA 5D73 18B1 E7EF A862 27AC 3FB8 9E3A 27C6 B0E4 +------------------------------------------------------------------+ Michael Andres SUSE LINUX Products GmbH, Development, ma@suse.de GF:Jeff Hawn,Jennifer Guild,Felix Imendörffer, HRB16746(AG Nürnberg) Maxfeldstrasse 5, D-90409 Nuernberg, Germany, ++49 (0)911 - 740 53-0 +------------------------------------------------------------------+ -- To unsubscribe, e-mail: zypp-devel+unsubscribe@opensuse.org To contact the owner, e-mail: zypp-devel+owner@opensuse.org
I tried the two ways here: 1. steps: 'select pattern base' 'deselect package A' 'resolve pool' Result: A, B, C, D 2. steps: 'select pattern base' 'resolve pool' 'deselect package A' Result: B, C, D I attached my source code, which was adapted to use the first way. And I have tested in openSUSE 12.2, it runs successfully, my chroot includes A, B, C, D however, instead of printing resolve problems. Thanks Gui -----Original Message----- From: Michael Andres [mailto:ma@suse.de] Sent: Wednesday, July 17, 2013 11:31 PM To: zypp-devel@opensuse.org Cc: Chen, Gui; Zhang, Qiang Z Subject: Re: [zypp-devel] excluding one package in a pattern in libzypp On Wednesday 17 July 2013 09:15:13 Chen, Gui wrote:
Hi list,
I am trying to create a chroot with libzypp, and I found when I need to remove a package and this package is part of a pattern which will be installed, the dependencies of the package will stay there. For example, if 'A' and 'C' are in a pattern 'base', and 'A' requires 'B', 'C' requires 'D', I need to install pattern 'base', also I need to set 'A' uninstalled, but I end up having 'B', 'C', 'D' in my chroot. If I am not installing 'A', I definitely needn't 'B' installed. Is there any comment? should I file a bug?
How did you do it? You can't 'install pattern:base' and 'remove A' in one step, because 'pattern:base requires A': 'select pattern:base' 'deselect A' 'resolve pool' (fails: pattern:base requires A') What you describe could be created this way: 'select pattern:base' 'resolve pool' (will select A C, B, D) 'deselect A' Here 'D' is still selected, but just because 'resolve pool' was not called after changing the selection. However, if a 'resolve pool' fails, the Resolver provides list of 'Resolver::problems()'. Each Problem usually has a list of solutions(). A ProblemSolution can be applied to the resolver. Problem 1: ==================================== pattern:base requires A, but this requirement cannot be provided ------------------------------------ Solutions for problem #1: ==================================== do not ask to delete all solvables providing A ------------------------------------ do not ask to install a solvable providing pattern:base ------------------------------------ ==> ignore some dependencies of pattern:base ------------------------------------ If I apply the last solution, then resolve again, I get C and D selected. -- cu, Michael Andres +------------------------------------------------------------------+ Key fingerprint = 2DFA 5D73 18B1 E7EF A862 27AC 3FB8 9E3A 27C6 B0E4 +------------------------------------------------------------------+ Michael Andres SUSE LINUX Products GmbH, Development, ma@suse.de GF:Jeff Hawn,Jennifer Guild,Felix Imendörffer, HRB16746(AG Nürnberg) Maxfeldstrasse 5, D-90409 Nuernberg, Germany, ++49 (0)911 - 740 53-0 +------------------------------------------------------------------+
On Thursday 18 July 2013 10:23:34 Chen, Gui wrote:
I tried the two ways here: 1. steps: 'select pattern base' 'deselect package A' 'resolve pool' Result: A, B, C, D ... I attached my source code, which was adapted to use the first way. And I have tested in openSUSE 12.2, it runs successfully, my chroot includes A, B, C, D however, instead of printing resolve problems.
I modified your code to print out the return values of the status changes you apply in mark_poolitem. (restore the location of your repo) === U_Tu_(6)pattern:base-.noarch(tmp) applied setToBeInstalled This is currently selected: U_Tu_(6)pattern:base-.noarch(tmp) === U__s_(5)A-0.1-1.x86_64(tmp) applied resetTransact === U__s_(5)A-0.1-1.x86_64(tmp) FAILED TO APPLY setToBeUninstalled This is currently selected: U_Tu_(6)pattern:base-.noarch(tmp) This would have been commited: U_Ts_(2)D-1.0-1.x86_64(tmp) U_Ts_(3)C-0.1-1.x86_64(tmp) U_Ts_(4)B-1.0-1.x86_64(tmp) U_Ts_(5)A-0.1-1.x86_64(tmp) USTu_(6)pattern:base-.noarch(tmp) Actually you did not deselect A. Only pattern:base is selected and resolved. That's why A,B,C,D are installed. Why? A PoolItem combines the basic data of a single package(pattern/patch/..) instance with a simple status. Package instances are found in the rpm database (@System) as well as in repositories. On a typical system you will have multiple instances of a package called e.g. "kernel": installed: kernel-1.0 (@System) kernel-1.1 (@System) available: kernel-1.0 (repo: foo) kernel-1.1 (repo: foo-updates) kernel-1.2 (repo: foo-updates) kernel-2.0 (repo: experimental) So you have 6 PoolItems named "kernel". The status of each PoolItem describes this instances fate: - unchanged: nothing happens - transacts: for an installed item it means it gets deleted; for an available item it means it gets installed; - locked: not allowed to change the status; raises a resolver conflict if a change would be necessary. In your case you requested setToBeUninstalled for an available PoolItem. As the item is not installed, the request can't be fulfilled. What you wanted is to lock A, in fact all available instances of A if there were multiple, so the solver will not be allowed to select any of them and raise a conflict instead. Obviously by looking at a single PoolItem you do not get the whole picture. You always need to consider all PoolItems for of given name in order to see what is, and what will happen. A 'normal' package update for example will cause the installed as well as one available PoolItem to 'transact'. Only in case multiple versions of a package can be installed in parallel (e.g. kernel), each PoolItem can be treated (more or less) independently. The above collection of all PoolItems of the same name is available as ui::Selectable. This class also allows to get/set an overall status for this 'name' (translating this into solver requests and adjusting the individual PoolItems): ui::Selectable::Ptr sel = ui::Selectable::get( "A" ); // (package) A if ( ! sel ) std::cout << "No package:A in the pool" << endl; else if ( ! sel->setStatus( ui::S_Taboo, ResStatus::USER ) ) std::cout << "FAILED to set S_Taboo on " << sel << endl; // ui::Selectable::get( ResKind::package, "A" ); // ui::Selectable::get( ResKind::pattern, "base" ); // ui::Selectable::get( IdString( "pattern:base" ) ); // also get from Solvable or PoolItem With the above fix, you get the desired resolver conflict. Choosing to ignore it. you get D,C installed: Problem: ============================== pattern:base-.noarch requires A, but this requirement cannot be provided uninstallable providers: A-0.1-1.x86_64[tmp] ------------------------------ Solution: do not forbid installation of A-0.1-1.x86_64[tmp] TransactionSolutionAction: Unlock U_Lu_(5)A-0.1-1.x86_64(tmp) Solution: do not install pattern:base-.noarch TransactionSolutionAction: Keep UBTu_(6)pattern:base-.noarch(tmp) Solution: break pattern:base-.noarch by ignoring some of its dependencies InjectSolutionAction: Weak UBTu_(6)pattern:base-.noarch(tmp) ============================== PICK LAST SOLUTION SOLVE AGAIN This would have been commited: U_Ts_(2)D-1.0-1.x86_64(tmp) U_Ts_(3)C-0.1-1.x86_64(tmp) UBTu_(6)pattern:base-.noarch(tmp) JFYI: There is also a way to directly file solver requests. It is currently a bit limited, as it just supports Capabilities (you 'd not be be asking for 'package A' but for 'something providing A', which is close, but not exactly the same). This API will be enhanced as it's probably nice to usee for simple tasks. ResPool pool( ResPool::instance() ); pool.resolver().addRequire( Capability("pattern:base") ); pool.resolver().addConflict( Capability("A") ); pool.resolver().resolvePool(); -- cu, Michael Andres +------------------------------------------------------------------+ Key fingerprint = 2DFA 5D73 18B1 E7EF A862 27AC 3FB8 9E3A 27C6 B0E4 +------------------------------------------------------------------+ Michael Andres SUSE LINUX Products GmbH, Development, ma@suse.de GF:Jeff Hawn,Jennifer Guild,Felix Imendörffer, HRB16746(AG Nürnberg) Maxfeldstrasse 5, D-90409 Nuernberg, Germany, ++49 (0)911 - 740 53-0 +------------------------------------------------------------------+
participants (2)
-
Chen, Gui
-
Michael Andres