Duncan Mac-Vicar P. wrote:
I would like others (especially Michael) to review it.
I am quoting the blocks of texts from the Wiki, which I would like to focus the discussion on.
Communication between the YCP application and the C++ package selector widgets is very limited (almost nonexistent). In particular, the YCP application cannot create a pool and pass a handle to that pool to the C++ package selector or vice versa.
Thus, for all important objects like pool or similar, there must be a singleton object for each that can easily be accessed from both the YCP code (via package bindings) and from the package selectors. Those singleton objects should live in the app layer.
My guess is, that there will be no need for the applications to manipulate the Pool directly as long as we have all the other API they need (the Query, content iterators of Patterns, etc.)
Selectables have a higher level status that is the result of the useful permutations of the status flags of their resolvables and the fact whether or not one resolvable from this selectable (one instance of that package) is already installed:
Matching Selectable and Resolvable Status and Candidate Handling The package selectors use the selectable status. They never store any selectable's status; they always retrieve the status when it is needed. When the user changes a selectable's status, they set new status and retrieve it for display so the display and the selectable status are always in sync.
Since selectable don't exist in the libzypp layer, matching a selectable status to the individual resolvable status flags is done by the app layer and vice versa. The app layer also keeps track of the candidate. This is important when the selectable status is used since some operations (install, update) implicitly operate on the candidate.
I think this is one of the central parts of the problem we need to solve.
What about merging NameKindProxy with Selectables? I mean to drop the NameKindProxy and allow a Selectable to have multiple target (installed) resolvables. See also this mail from Michael, the second half: http://lists4.suse.de/yast-devel/2007-06/msg00150.html I quite agree with Michael there and i came to the same conclusion recently. I don't mean using Selectables as Pool objects (i don't have much solver knowledge), but the others, namely: "It would be a good place to provide convenient status manipulating methods.", installation candidate handling. Also it would be a good place for a 'contents' iterator (whatever it would mean from the implementation POV). I guess this is also consistent with what Klaus says in the other mail [1] in this thread. Can this be done? While i know that we want to be able to have multiple versions of a resolvable to be installed, i don't know why this case needs to be represented by multiple Selectables instead of one (which has multiple target resolvables). Would it be harder or even impossible for the UIs to handle?
As long as the user did not explicitly choose a specific candidate, the app layer automatically chooses one from the available resolvables. That automatic choice takes matching architectures and most recent version number into account.
This is not trivial. Right now the UIs do this choices in some random code somewhere in the UI, or using the selectable candidate function, which is now incomplete. This kind of decision is the same as the solver local policy. So we have to connect them trough the API somehow. Imagine this something like:
bestCandidate( list_of_candidates, task )
Of course this has to be in Selectable, but it has to be connected to the local policy, and it depends on the task you want to execute.
Otherwise the UIs will continue breaking things like vendor (the UIs iterate over a package list and select the higher version instead of the best candidate according to the system policies ).
I bet we all agree on this, this stuff must be handled in libzypp. Before we continue to discuss this, let's settle on the term 'selectable' so that we know what we talk about. See my mail "Selectables and 'candidate'".
Patterns (collections of packages to fulfil a certain task)
This is where the UI <-> library problems starts. What the wiki describes there is the description of a Selection.
That's just a problem of agreeing on usage of the words. I see no _real_ problem here. The bottom line is, the UIs need to show what's inside a pattern - libzypp must provide an API to enumerate something to display. Once we agree on this, the rest is not such a big problem. We don't need to argue about words (although i agree we should speak as precisely as the subject requires when discussing technical matters).
Technically, none of those higher level objects has a package content: They all just have dependencies that typically (but not necessarily) are satisfied by packages.
Exactly.
From a user's point of view, however, those higher level objects are nothing else than containers for packages. Though this is a somewhat simplistic view, users typically want to see what is behind a pattern, a patch, or a language resolvable. This is why each of them should have a mechanism to enumerate the packages that belong to them.
This is true, but only if you can live with the true: the mechanism to enumerate the list of packages is just an algorithm, not a list. It can be false information.
That is why I tried to start using the term "related packages" instead of "content".
Again, this is 'just' about words. What we need is the API :O) Let's have Selectable::contents{Begin,End,Size}(), whatever we put inside. Now for searching. It was suggested that there should be a class handling the queries - thus zypp::ui::Query. Based on requirements and Bubli's (and my own) proposal, i've written the Query.h (see attached):
The user can select any one of those search modes:
* Contains * Begins with * Exact match
enum MatchLevel { MATCH_ANY_SUBSTRING, MATCH_WHOLE_WORDS, MATCH_EXACT_PHRASE, MATCH_BEGINNING, MATCH_END }; void Query::setMatchLevel(const MatchLevel level) { _match_level = level; } Maybe the MatchLevel should be in the addName() and addAttribute() methods, not for the whole Query?
* Use wildcards (*, ?)
If the queries will be implemented with regexes, any wildards in the search strings will be converted to correspondent regex sequences.
* Use regular expression
note the isRegex parameter: void Query::addName(const std::string & name, bool is_regexp = false); void addAttribute(const Attribute & attrid, const std::string & value, bool isRegex = false);
Case sensitivity in all searches can be switched on or off.
void Query::setCaseSensitive(const bool value = true); ==== Another thingy to solve is the combination of several queries, e.g. give two or three strings, match packages containg ALL of them, or ANY of them. Some basic degree of this could be provided by: void setRequireAll(bool require_all = true); which would serve as AND operator if true, and OR if false to combine all the conditions added to the Query with addName() and addAttribute() (or even addDependency()). Not much flexiblity, but the question is also whether we need more. ==== If you agree, i'll commit the file to svn trunk and we can polish it there. If it is fundamentally wrong, i'll rewrite it and check with you agin :O)
A query engine to replace this functionality in the UI should enumerate (return an iterator to) the selectables that match the given criteria.
Update Problems Filter View This filter view enumerates those packages that for one reason or the other could not automatically be updated during a system update. Adding packages to this list is done by the system update application layer.
And what is the criteria for searching those?
Again, whatever is the answer to this question, the API must be there somewhere in libzypp, so that the UIs can just use it and not implment it on their own.
Libzypp/Application Layer/API Proposal
enum Type { PACKAGE, PATTERN, PATCH, LANGUAGE }
Why resolvable kind can't be used here? Why the need to duplicate it?
No need to duplicate, it was meant only as a demonstration. Of course we will use Resolvable::Kind, but maybe it would be nice to have an enumeration of currently used kinds.
* Create pool iterator (based on the above query as a parameter)
Pool pool = new Pool (q);
So this is like a pool proxy based on a query? Why not the iterator taking the query as a parameter (Michael could comment more?)
I have one concern with the design of the pool based on queries. It means we have to load the pool data, this will not be bad with the sat solver, but this is not the same zypper does, as zypper only gets the resolvable data to be displayed on the screen, without any pool.
Dropped in the actual API proposal, see Query.h in the attachment.
Other API that could be part of the zypp layer is a command oriented api.
If you look what API smart offers to the UIs is a much simpler API, and it is the same the command line tool offers, and this is quite similar to all zypper code.
It defines a Command class (install, search, etc) it defines a abstract interface for callbacks (confirm dialogs, progress, questions, etc) The UI simply creates a command and executes it.
This is a much simpler approach, but I think it is needed in addition to the layer our selector need.
Both packagekit and any app wanting to install a package could benefit from this.
The is interesting, but i would rather discuss it in a separate thread. Also it probably something for post 11.0 releases. [1] http://lists4.suse.de/zypp-devel/2008-02/msg00018.html