Hello community,

here is the log from the commit of package yast2-pkg-bindings for 
openSUSE:Factory checked in at 2019-07-31 14:16:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-pkg-bindings (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-pkg-bindings.new.4126 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-pkg-bindings"

Wed Jul 31 14:16:45 2019 rev:205 rq:706661 version:4.2.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-pkg-bindings/yast2-pkg-bindings.changes    
2019-03-12 09:50:53.407568256 +0100
+++ 
/work/SRC/openSUSE:Factory/.yast2-pkg-bindings.new.4126/yast2-pkg-bindings.changes
  2019-07-31 14:16:48.114712540 +0200
@@ -1,0 +2,7 @@
+Thu May 23 07:09:08 UTC 2019 - Ladislav Slezák <[email protected]>
+
+- Added Pkg.Resolvables() and Pkg.AnyResolvable() calls
+  (related to bsc#1132650)
+- 4.2.0
+
+-------------------------------------------------------------------

Old:
----
  yast2-pkg-bindings-4.1.2.tar.bz2

New:
----
  yast2-pkg-bindings-4.2.0.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-pkg-bindings-devel-doc.spec ++++++
--- /var/tmp/diff_new_pack.zEM52b/_old  2019-07-31 14:16:48.746712368 +0200
+++ /var/tmp/diff_new_pack.zEM52b/_new  2019-07-31 14:16:48.750712367 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-pkg-bindings-devel-doc
-Version:        4.1.2
+Version:        4.2.0
 Release:        0
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 Source0:        yast2-pkg-bindings-%{version}.tar.bz2

++++++ yast2-pkg-bindings.spec ++++++
--- /var/tmp/diff_new_pack.zEM52b/_old  2019-07-31 14:16:48.770712361 +0200
+++ /var/tmp/diff_new_pack.zEM52b/_new  2019-07-31 14:16:48.770712361 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-pkg-bindings
-Version:        4.1.2
+Version:        4.2.0
 Release:        0
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build

++++++ yast2-pkg-bindings-4.1.2.tar.bz2 -> yast2-pkg-bindings-4.2.0.tar.bz2 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pkg-bindings-4.1.2/Dockerfile 
new/yast2-pkg-bindings-4.2.0/Dockerfile
--- old/yast2-pkg-bindings-4.1.2/Dockerfile     2019-03-08 13:05:55.000000000 
+0100
+++ new/yast2-pkg-bindings-4.2.0/Dockerfile     2019-05-27 09:27:48.000000000 
+0200
@@ -1,4 +1,4 @@
-FROM yastdevel/cpp
+FROM registry.opensuse.org/yast/head/containers/yast-cpp:latest
 RUN zypper --gpg-auto-import-keys --non-interactive in --no-recommends \
   libzypp-devel yast2-ruby-bindings iproute2
 COPY . /usr/src/app
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-pkg-bindings-4.1.2/package/yast2-pkg-bindings-devel-doc.spec 
new/yast2-pkg-bindings-4.2.0/package/yast2-pkg-bindings-devel-doc.spec
--- old/yast2-pkg-bindings-4.1.2/package/yast2-pkg-bindings-devel-doc.spec      
2019-03-08 13:05:55.000000000 +0100
+++ new/yast2-pkg-bindings-4.2.0/package/yast2-pkg-bindings-devel-doc.spec      
2019-05-27 09:27:48.000000000 +0200
@@ -16,7 +16,7 @@
 #
 
 Name:           yast2-pkg-bindings-devel-doc
-Version:        4.1.2
+Version:        4.2.0
 Release:        0
 License:        GPL-2.0-only
 Group:          Documentation/HTML
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-pkg-bindings-4.1.2/package/yast2-pkg-bindings.changes 
new/yast2-pkg-bindings-4.2.0/package/yast2-pkg-bindings.changes
--- old/yast2-pkg-bindings-4.1.2/package/yast2-pkg-bindings.changes     
2019-03-08 13:05:55.000000000 +0100
+++ new/yast2-pkg-bindings-4.2.0/package/yast2-pkg-bindings.changes     
2019-05-27 09:27:48.000000000 +0200
@@ -1,4 +1,11 @@
 -------------------------------------------------------------------
+Thu May 23 07:09:08 UTC 2019 - Ladislav Slezák <[email protected]>
+
+- Added Pkg.Resolvables() and Pkg.AnyResolvable() calls
+  (related to bsc#1132650)
+- 4.2.0
+
+-------------------------------------------------------------------
 Fri Mar  8 11:44:51 UTC 2019 - [email protected]
 
 - zypp::TriBool now needs an explicit cast to bool (bsc#1128364)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-pkg-bindings-4.1.2/package/yast2-pkg-bindings.spec 
new/yast2-pkg-bindings-4.2.0/package/yast2-pkg-bindings.spec
--- old/yast2-pkg-bindings-4.1.2/package/yast2-pkg-bindings.spec        
2019-03-08 13:05:55.000000000 +0100
+++ new/yast2-pkg-bindings-4.2.0/package/yast2-pkg-bindings.spec        
2019-05-27 09:27:48.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-pkg-bindings
-Version:        4.1.2
+Version:        4.2.0
 Release:        0
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pkg-bindings-4.1.2/smoke_test_run.rb 
new/yast2-pkg-bindings-4.2.0/smoke_test_run.rb
--- old/yast2-pkg-bindings-4.1.2/smoke_test_run.rb      2019-03-08 
13:05:55.000000000 +0100
+++ new/yast2-pkg-bindings-4.2.0/smoke_test_run.rb      2019-05-27 
09:27:48.000000000 +0200
@@ -16,7 +16,7 @@
 # to y2log without affecting the return value :-(
 def check_y2log
   y2log = File.read(log_file).split("\n")
-  
+
   # keep only errors and higher
   y2log.select! { |l| l =~ /^[0-9]{4}-[0-9]{2}-[0-9]{2} 
[0-9]{2}:[0-9]{2}:[0-9]{2} <[3-5]>/ }
 
@@ -28,7 +28,7 @@
   # ignore "Can't openfile '/var/lib/zypp/LastDistributionFlavor' for writing"
   # (when running as non-root)
   y2log.reject! { |l| l =~ /\/var\/lib\/zypp\/LastDistributionFlavor/ }
-  
+
   if !y2log.empty?
     puts "Found errors in #{log_file}:"
     puts y2log
@@ -80,5 +80,31 @@
 end
 puts "OK"
 
+# Check all packages - this expects at least one package is available/installed
+puts "Checking Pkg.Resolvabless..."
+resolvables = Yast::Pkg.Resolvables({kind: :package}, [])
+raise "Pkg.Resolvables failed!" unless resolvables
+raise "No package found!" if resolvables.empty?
+# compare with the old Pkg.ResolvableProperties call
+raise "Different number of packages found!" if packages.size != 
resolvables.size
+puts "OK (found #{resolvables.size} packages)"
+
+patterns = Yast::Pkg.Resolvables({kind: :pattern}, [:name])
+raise "Pkg.Resolvables failed!" unless patterns
+raise "No pattern found!" if patterns.empty?
+raise "Pattern devel_yast not found" unless patterns.include?("name" => 
"devel_yast")
+puts "OK (found #{patterns.size} patterns)"
+
+installed_products = Yast::Pkg.Resolvables({kind: :product, status: 
:installed}, [:name, :display_name])
+available_products = Yast::Pkg.Resolvables({kind: :product, status: 
:available}, [:name, :display_name])
+selected_products = Yast::Pkg.Resolvables({kind: :product, status: :selected}, 
[:name, :display_name])
+raise "Pkg.Resolvables failed!" unless patterns
+raise "No installed product found!" if installed_products.empty?
+raise "No available product found!" if available_products.empty?
+raise "A selected product found, nothing should be selected now!" unless 
selected_products.empty?
+puts "Found #{installed_products.size} installed products: 
#{installed_products.map{|p| p["display_name"]}}"
+puts "Found #{available_products.size} available products: 
#{available_products.map{|p| p["display_name"]}}"
+puts "OK"
+
 # scan y2log for errors
 check_y2log
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pkg-bindings-4.1.2/src/PkgFunctions.h 
new/yast2-pkg-bindings-4.2.0/src/PkgFunctions.h
--- old/yast2-pkg-bindings-4.1.2/src/PkgFunctions.h     2019-03-08 
13:05:55.000000000 +0100
+++ new/yast2-pkg-bindings-4.2.0/src/PkgFunctions.h     2019-05-27 
09:27:48.000000000 +0200
@@ -215,7 +215,7 @@
 
       bool CreateBaseProductSymlink();
 
-      YCPMap Resolvable2YCPMap(const zypp::PoolItem &item, const std::string 
&req_kind, bool dependencies);
+      YCPMap Resolvable2YCPMap(const zypp::PoolItem &item, bool all, bool 
deps, const YCPList &attrs);
 
       // CommitPolicy used for commit
       zypp::ZYppCommitPolicy *commit_policy;
@@ -766,6 +766,11 @@
        /* TYPEINFO: boolean(symbol,symbol)*/
        YCPValue IsAnyResolvable(const YCPSymbol& kind_r, const YCPSymbol& 
status);
 
+       /* TYPEINFO: list<map<string,any> >(map<symbol,any>, list<symbol>) */
+       YCPValue Resolvables(const YCPMap& filter, const YCPList& attrs);
+       /* TYPEINFO: boolean(map<symbol,any>) */
+       YCPValue AnyResolvable(const YCPMap& filter);
+
        // keyring related
        /* TYPEINFO: boolean(string,boolean)*/
        YCPValue ImportGPGKey(const YCPString& filename, const YCPBoolean& 
trusted);
@@ -821,7 +826,7 @@
     /* TYPEINFO: boolean(string) */
     YCPValue UrlSchemeIsDownloading(const YCPString &url_scheme);
 
-        YCPValue ResolvablePropertiesEx(const YCPString& name, const 
YCPSymbol& kind_r, const YCPString& version, bool dependencies);
+       YCPValue ResolvablePropertiesEx(const YCPString& name, const YCPSymbol& 
kind_r, const YCPString& version, bool all, bool deps, const YCPList &attrs);
        YCPValue ResolvableSetPatches(const YCPSymbol& kind_r, bool preselect);
 
   /* TYPEINFO: integer(string, string) */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-pkg-bindings-4.1.2/src/Resolvable_Properties.cc 
new/yast2-pkg-bindings-4.2.0/src/Resolvable_Properties.cc
--- old/yast2-pkg-bindings-4.1.2/src/Resolvable_Properties.cc   2019-03-08 
13:05:55.000000000 +0100
+++ new/yast2-pkg-bindings-4.2.0/src/Resolvable_Properties.cc   2019-05-27 
09:27:48.000000000 +0200
@@ -56,19 +56,20 @@
    @description
    return list of resolvables of selected kind with required name
 
+   **Obsolete**
+
+   This call is obsolete, use `Resolvables()` call instead, it has more 
filtering
+   options and allows to return only the selected keys (saves memory and time).
+
    **Warning**
 
    Calling `ResolvableProperties("", :package, "")` variant is memory expansive
    esp. when there are repositories with too many packages (e.g. the OpenSUSE
    OSS repository contains ~40,000 packages).
 
-   If you need only packages in a specific state then use `GetPackages()` call
-   instead. If you need more details about the packages then read the details 
only
-   for that packages using `ResolvableProperties(package_name, :package, "")`.
-   In some cases it is also possible to use the `IsAnyResolvable` call.
-
-   The other resolvable types (e.g. :pattern or :product) do not cause memory
-   problems as there are usually just few items of this type.
+   It is recommended to use the `Resolvables()` call instead and use a more 
specific
+   input filter. If you only need a boolean result if a certain resolvable 
exists
+   then use the `AnyResolvable` call.
 
    See bsc#106768.
 
@@ -85,11 +86,13 @@
    if status is `selected or `removed there is extra key "transact_by" : 
symbol, where symbol is `user (the highest level),
        `app_high (selected by Yast), `app_low and `solver (the lowest level)
    on_system_by_user shows if the resolvable has been installed by 
user(USER,APPL_HIGH,APPL_LOW) or due solved dependencies. This information 
comes from
-     the solver which cannot distinguis between the state USER,APPL_HIGH and 
APPL_LOW.
+     the solver which cannot distinguish between the state USER,APPL_HIGH and 
APPL_LOW.
 
      "version" value contains edition with all components in form 
"[epoch:]version[-release]",
      "version_epoch", "version_version" and "version_release" values contain 
the parts of the edition.
 
+        The "kind" attribute contains the kind of the resolvable, it can be 
either :package, :patch, :product, :srcpackage or :pattern.
+
      Additionally to keys returned for all resolvables, there also some
      resolvable-specific ones:
 
@@ -171,7 +174,10 @@
 YCPValue
 PkgFunctions::ResolvableProperties(const YCPString& name, const YCPSymbol& 
kind_r, const YCPString& version)
 {
-    return ResolvablePropertiesEx (name, kind_r, version, false);
+       y2warning("Pkg::ResolvableProperties() is obsolete.");
+       y2warning("Use Pkg::Resolvables({name: ..., kind: ...}, [...]) 
instead.");
+
+       return ResolvablePropertiesEx (name, kind_r, version, true, false, 
YCPList());
 }
 
 /*
@@ -184,7 +190,10 @@
 YCPValue
 PkgFunctions::ResolvableDependencies(const YCPString& name, const YCPSymbol& 
kind_r, const YCPString& version)
 {
-    return ResolvablePropertiesEx (name, kind_r, version, true);
+       y2warning("Pkg::ResolvableDependencies() is obsolete.");
+       y2warning("Use Pkg::Resolvables({name: ..., kind: ...}, [:dependencies, 
...]) instead.");
+
+       return ResolvablePropertiesEx (name, kind_r, version, true, true, 
YCPList());
 }
 
 std::string PkgFunctions::TransactToString(zypp::ResStatus::TransactByValue 
trans)
@@ -202,388 +211,337 @@
     return ret;
 }
 
-YCPMap PkgFunctions::Resolvable2YCPMap(const zypp::PoolItem &item, const 
std::string &req_kind, bool dependencies)
+YCPMap PkgFunctions::Resolvable2YCPMap(const zypp::PoolItem &item, bool all, 
bool deps, const YCPList &attrs)
 {
     YCPMap info;
 
-    info->add(YCPString("name"), YCPString(item->name()));
+// define some helper macros
+#define ADD_STRING(K, V) \
+       if (all || attrs->contains(YCPSymbol(K))) \
+               info->add(YCPString(K), YCPString(V));
+#define ADD_BOOLEAN(K, V) \
+       if (all || attrs->contains(YCPSymbol(K))) \
+               info->add(YCPString(K), YCPBoolean(V));
+#define ADD_INTEGER(K, V) \
+       if (all || attrs->contains(YCPSymbol(K))) \
+               info->add(YCPString(K), YCPInteger(V));
+#define ADD_SYMBOL(K, V) \
+       if (all || attrs->contains(YCPSymbol(K))) \
+               info->add(YCPString(K), YCPSymbol(V));
+#define ADD_NOT_EMPTY_LIST(K, V) \
+               if ((all && !(V).isEmpty()) || attrs->contains(YCPSymbol(K))) \
+                       info->add(YCPString(K), V);
+#define ADD_NOT_EMPTY_STRING(K, V) \
+               if ((all && !(V).empty()) || attrs->contains(YCPSymbol(K))) \
+                       info->add(YCPString(K), YCPString(V));
+
+       ADD_STRING("name", item->name());
     // complete edition: [epoch:]version[-release]
-    info->add(YCPString("version"), YCPString(item->edition().asString()));
+       ADD_STRING("version", item->edition().asString());
+       ADD_STRING("version_version", item->edition().version());
+       ADD_STRING("version_release", item->edition().release());
 
     // parts of the edition
-    if (item->edition().epoch() == zypp::Edition::noepoch)
-        info->add(YCPString("version_epoch"), YCPVoid());
-    else
-        info->add(YCPString("version_epoch"), 
YCPInteger(item->edition().epoch()));
-    info->add(YCPString("version_version"), 
YCPString(item->edition().version()));
-    info->add(YCPString("version_release"), 
YCPString(item->edition().release()));
+       if (all || attrs->contains(YCPSymbol("version_epoch")))
+       {
+               if (item->edition().epoch() == zypp::Edition::noepoch)
+                       info->add(YCPString("version_epoch"), YCPVoid());
+               else
+                       info->add(YCPString("version_epoch"), 
YCPInteger(item->edition().epoch()));
+       }
 
-    info->add(YCPString("arch"), YCPString(item->arch().asString()));
-    info->add(YCPString("description"), YCPString(item->description()));
+       ADD_STRING("arch", item->arch().asString());
+       ADD_STRING("description", item->description());
 
     std::string resolvable_summary = item->summary();
-    if (resolvable_summary.size() > 0)
-    {
-       info->add(YCPString("summary"), YCPString(resolvable_summary));
-    }
-
-    // status
-    std::string stat;
+       ADD_NOT_EMPTY_STRING("summary", resolvable_summary);
 
     zypp::ResStatus status = item.status();
 
-    if (status.isToBeInstalled())
-    {
-       stat = "selected";
-    }
-    else if (status.isInstalled() || status.isSatisfied())
-    {
-       if (status.isToBeUninstalled())
-       {
-           stat = "removed";
-       }
-       else
+    // status
+       if (all || attrs->contains(YCPSymbol("status")))
        {
-           stat = "installed";
-       }
-    }
-    else
-    {
-       stat = "available";
-    }
+               std::string stat;
 
-    info->add(YCPString("transact_by"), 
YCPSymbol(TransactToString(status.getTransactByValue())));
+               if (status.isToBeInstalled())
+                       stat = "selected";
+               else if (status.isInstalled() || status.isSatisfied())
+                       stat = (status.isToBeUninstalled()) ? "removed" : 
"installed";
+               else
+                       stat = "available";
 
-    info->add(YCPString("on_system_by_user"), 
YCPBoolean(item.satSolvable().onSystemByUser()));
-
-    info->add(YCPString("status"), YCPSymbol(stat));
+           info->add(YCPString("status"), YCPSymbol(stat));
+       }
 
+       ADD_SYMBOL("transact_by", 
TransactToString(status.getTransactByValue()));
+       ADD_BOOLEAN("on_system_by_user", item.satSolvable().onSystemByUser());
     // is the resolvable locked? (Locked or Taboo in the UI)
-    info->add(YCPString("locked"), YCPBoolean(status.isLocked()));
-
+       ADD_BOOLEAN("locked", status.isLocked());
     // source
-    info->add(YCPString("source"), 
YCPInteger(logFindAlias(item->repoInfo().alias())));
+       ADD_INTEGER("source", logFindAlias(item->repoInfo().alias()));
 
     // add license info if it is defined
     std::string license = item->licenseToConfirm();
-    if (!license.empty())
-    {
-       info->add(YCPString("license_confirmed"), 
YCPBoolean(item.status().isLicenceConfirmed()));
-       info->add(YCPString("license"), YCPString(license));
-    }
-
-    info->add(YCPString("download_size"), YCPInteger(item->downloadSize()));
-    info->add(YCPString("inst_size"), YCPInteger(item->installSize()));
-
-    info->add(YCPString("medium_nr"), YCPInteger(item->mediaNr()));
-    info->add(YCPString("vendor"), YCPString(item->vendor()));
+    if ((all && !license.empty()) || 
attrs->contains(YCPSymbol("license_confirmed")))
+       {
+               info->add(YCPString("license_confirmed"), 
YCPBoolean(item.status().isLicenceConfirmed()));
+               info->add(YCPString("license"), YCPString(license));
+       }
 
+       ADD_INTEGER("download_size", item->downloadSize());
+       ADD_INTEGER("inst_size", item->installSize());
+       ADD_INTEGER("medium_nr", item->mediaNr());
+       ADD_STRING("vendor", item->vendor());
 
     // package specific info
-    if( req_kind == "package" )
-    {
        zypp::Package::constPtr pkg = 
zypp::asKind<zypp::Package>(item.resolvable());
-       if ( pkg )
-       {
-           std::string tmp = pkg->location().filename().asString();
-           if (!tmp.empty())
-           {
-               info->add(YCPString("path"), YCPString(tmp));
-           }
-
-           tmp = pkg->location().filename().basename();
-           if (!tmp.empty())
-           {
-               info->add(YCPString("location"), YCPString(tmp));
-           }
-       } else
-       {
-           y2error("package %s is not a package", item->name().c_str() );
-       }
-    }
-    else if( req_kind == "srcpackage" )
-    {
-       zypp::SrcPackage::constPtr pkg = 
zypp::asKind<zypp::SrcPackage>(item.resolvable());
        if (pkg)
        {
-           std::string tmp(pkg->location().filename().asString());
-           if (!tmp.empty())
-           {
-               info->add(YCPString("path"), YCPString(tmp));
-           }
-
-           tmp = pkg->location().filename().basename();
-           if (!tmp.empty())
-           {
-               info->add(YCPString("location"), YCPString(tmp));
-           }
-
-           info->add(YCPString("src_type"), YCPString(pkg->sourcePkgType()));
-       }
-       else
-       {
-           y2error("%s is not a srcpackage", item->name().c_str() );
-       }
-    }
-    // product specific info
-    else if( req_kind == "product" ) {
-       zypp::Product::constPtr product = 
zypp::asKind<zypp::Product>(item.resolvable());
-       if ( !product )
-       {
-           y2error("product %s is not a product", item->name().c_str() );
-           return YCPMap();
-       }
-
-       std::string category(product->isTargetDistribution() ? "base" : 
"addon");
+               ADD_SYMBOL("kind", "package");
 
-       info->add(YCPString("category"), YCPString(category));
-       info->add(YCPString("type"), YCPString(category));
-       info->add(YCPString("relnotes_url"), 
YCPString(product->releaseNotesUrls().first().asString()));
+               std::string path = pkg->location().filename().asString();
+               ADD_NOT_EMPTY_STRING("path", path);
 
-       std::string product_summary = product->summary();
-       if (product_summary.size() > 0)
-       {
-           info->add(YCPString("display_name"), YCPString(product_summary));
+               std::string location = pkg->location().filename().basename();
+               ADD_NOT_EMPTY_STRING("location", location);
        }
 
-       std::string product_shortname = product->shortName();
-       if (product_shortname.size() > 0)
+       zypp::SrcPackage::constPtr src_pkg = 
zypp::asKind<zypp::SrcPackage>(item.resolvable());
+       if (src_pkg)
        {
-           info->add(YCPString("short_name"), YCPString(product_shortname));
-       }
-       // use summary for the short name if it's defined
-       else if (product_summary.size() > 0)
-       {
-           info->add(YCPString("short_name"), YCPString(product_summary));
-       }
+               ADD_SYMBOL("kind", "srcpackage");
 
-        zypp::Date eol = product->endOfLife();
-        if (eol > 0)
-        {
-          info->add(YCPString("eol"), YCPInteger(eol));
-        }
+               std::string path = src_pkg->location().filename().asString();
+               ADD_NOT_EMPTY_STRING("path", path);
 
-       YCPList updateUrls(asYCPList(product->updateUrls()));
-       info->add(YCPString("update_urls"), updateUrls);
+               std::string location = 
src_pkg->location().filename().basename();
+               ADD_NOT_EMPTY_STRING("location", location);
 
-       YCPList flags;
-       std::list<std::string> pflags = product->flags();
-       for (std::list<std::string>::const_iterator flag_it = pflags.begin();
-           flag_it != pflags.end(); ++flag_it)
-       {
-           flags->add(YCPString(*flag_it));
+               ADD_STRING("src_type", src_pkg->sourcePkgType());
        }
-       info->add(YCPString("flags"), flags);
 
-       YCPList extraUrls( asYCPList(product->extraUrls()) );
-       if ( extraUrls.size() )
+       zypp::Product::constPtr product = 
zypp::asKind<zypp::Product>(item.resolvable());
+       if ( product )
        {
-         info->add(YCPString("extra_urls"), extraUrls);
-       }
+               ADD_SYMBOL("kind", "product");
 
-       YCPList optionalUrls( asYCPList(product->optionalUrls()) );
-       if ( optionalUrls.size() )
-       {
-         info->add(YCPString("optional_urls"), optionalUrls);
-       }
+               std::string category(product->isTargetDistribution() ? "base" : 
"addon");
 
-       YCPList registerUrls( asYCPList(product->registerUrls()) );
-       if ( registerUrls.size() )
-       {
-         info->add(YCPString("register_urls"), registerUrls);
-       }
+               ADD_STRING("category", category);
+               ADD_STRING("type", category);
+               ADD_STRING("relnotes_url", 
product->releaseNotesUrls().first().asString());
 
-       YCPList smoltUrls( asYCPList(product->smoltUrls()) );
-       if ( smoltUrls.size() )
-       {
-         info->add(YCPString("smolt_urls"), smoltUrls);
-       }
+               std::string product_summary = product->summary();
+               ADD_STRING("display_name", product_summary);
 
-       YCPList relNotesUrls(asYCPList(product->releaseNotesUrls()));
-       if ( relNotesUrls.size() )
-       {
-         info->add(YCPString("relnotes_urls"), relNotesUrls);
-       }
+               if (all || attrs->contains(YCPSymbol("short_name")))
+               {
+                       std::string product_shortname = product->shortName();
+                       ADD_NOT_EMPTY_STRING("short_name", product_shortname)
+                       else if (!product_summary.empty())
+                               // use summary for the short name if it's 
defined
+                               info->add(YCPString("short_name"), 
YCPString(product_summary));
+               }
 
-       // registration data
-       info->add(YCPString("register_target"), 
YCPString(product->registerTarget()));
-       info->add(YCPString("register_release"), 
YCPString(product->registerRelease()));
-       info->add(YCPString("register_flavor"), 
YCPString(product->registerFlavor()));
-       info->add(YCPString("product_line"), YCPString(product->productLine()));
+               if ((all && product->endOfLife() > 0) || 
attrs->contains(YCPSymbol("eol")))
+          info->add(YCPString("eol"), YCPInteger(product->endOfLife()));
 
-       // Live CD, FTP Edition...
-       info->add(YCPString("flavor"), YCPString(product->flavor()));
+               if (all || attrs->contains(YCPSymbol("update_urls")))
+               {
+                       YCPList updateUrls(asYCPList(product->updateUrls()));
+                       info->add(YCPString("update_urls"), updateUrls);
+               }
 
-       // get the installed Products it would replace.
-       zypp::Product::ReplacedProducts replaced(product->replacedProducts());
+               if (all || attrs->contains(YCPSymbol("flags")))
+               {
+                       YCPList flags;
 
-       if (!replaced.empty())
-       {
-           YCPList rep_prods;
+                       for (auto const &flag : product->flags())
+                               flags->add(YCPString(flag));
 
-           // add the products to the list
-           for_( it, replaced.begin(), replaced.end() )
-           {
-               // The current replaced Product.
-               zypp::Product::constPtr replacedProduct(*it);
+                       info->add(YCPString("flags"), flags);
+               }
 
-               if (!replacedProduct) continue;
+               YCPList extraUrls( asYCPList(product->extraUrls()) );
+               ADD_NOT_EMPTY_LIST("extra_urls", extraUrls);
 
-               YCPMap rprod;
-               rprod->add(YCPString("name"), 
YCPString(replacedProduct->name()));
-               rprod->add(YCPString("version"), 
YCPString(replacedProduct->edition().asString()));
-               rprod->add(YCPString("arch"), 
YCPString(replacedProduct->arch().asString()));
-               rprod->add(YCPString("description"), 
YCPString(replacedProduct->description()));
+               YCPList optionalUrls( asYCPList(product->optionalUrls()) );
+               ADD_NOT_EMPTY_LIST("optional_urls", optionalUrls);
 
-               std::string product_summary = replacedProduct->summary();
-               if (product_summary.size() > 0)
-               {
-                   rprod->add(YCPString("display_name"), 
YCPString(product_summary));
-               }
+               YCPList registerUrls( asYCPList(product->registerUrls()) );
+               ADD_NOT_EMPTY_LIST("register_urls", registerUrls);
 
-               std::string product_shortname = replacedProduct->shortName();
-               if (product_shortname.size() > 0)
-               {
-                   rprod->add(YCPString("short_name"), 
YCPString(product_shortname));
-               }
-               // use summary for the short name if it's defined
-               else if (product_summary.size() > 0)
+               YCPList smoltUrls( asYCPList(product->smoltUrls()));
+               ADD_NOT_EMPTY_LIST("smolt_urls", smoltUrls);
+
+               YCPList relNotesUrls(asYCPList(product->releaseNotesUrls()));
+               ADD_NOT_EMPTY_LIST("relnotes_urls", relNotesUrls);
+
+               // registration data
+               ADD_STRING("register_target", product->registerTarget());
+               ADD_STRING("register_release", product->registerRelease());
+               ADD_STRING("register_flavor", product->registerFlavor());
+               ADD_STRING("product_line", product->productLine());
+               // Live CD, FTP Edition...
+               ADD_STRING("flavor", product->flavor());
+
+               // get the installed Products it would replace.
+               zypp::Product::ReplacedProducts 
replaced(product->replacedProducts());
+               if ((all && !replaced.empty()) || 
attrs->contains(YCPSymbol("replaces")))
                {
-                   rprod->add(YCPString("short_name"), 
YCPString(product_summary));
-               }
-           }
+                       YCPList rep_prods;
 
-           info->add(YCPString("replaces"), rep_prods);
-       }
-
-       std::string product_file;
+                       // add the products to the list
+                       for (auto const &replacedProduct : replaced)
+                       {
+                               if (!replacedProduct) continue;
 
-       // add reference file in /etc/products.d
-       if (status.isInstalled())
-       {
-           product_file = (_target_root + "/etc/products.d/" + 
product->referenceFilename()).asString();
-           y2milestone("Parsing product file %s", product_file.c_str());
-           const zypp::parser::ProductFileData productFileData = 
zypp::parser::ProductFileReader::scanFile(product_file);
+                               YCPMap rprod;
+                               rprod->add(YCPString("name"), 
YCPString(replacedProduct->name()));
+                               rprod->add(YCPString("version"), 
YCPString(replacedProduct->edition().asString()));
+                               rprod->add(YCPString("arch"), 
YCPString(replacedProduct->arch().asString()));
+                               rprod->add(YCPString("description"), 
YCPString(replacedProduct->description()));
+
+                               std::string product_summary = 
replacedProduct->summary();
+                               ADD_NOT_EMPTY_STRING("display_name", 
product_summary);
+
+                               std::string product_shortname = 
replacedProduct->shortName();
+                               ADD_NOT_EMPTY_STRING("short_name", 
product_shortname)
+                               // use summary for the short name if it's 
defined
+                               else if (product_summary.size() > 0)
+                                       rprod->add(YCPString("short_name"), 
YCPString(product_summary));
+                       }
 
-           YCPList upgrade_list;
+                       info->add(YCPString("replaces"), rep_prods);
+               }
 
-           for_( upit, productFileData.upgrades().begin(), 
productFileData.upgrades().end() )
-           {
-             const zypp::parser::ProductFileData::Upgrade & upgrade( *upit );
+               std::string product_file;
 
-             YCPMap upgrades;
-             upgrades->add(YCPString("name"), YCPString(upgrade.name()));
-             upgrades->add(YCPString("summary"), YCPString(upgrade.summary()));
-             upgrades->add(YCPString("repository"), 
YCPString(upgrade.repository()));
-             upgrades->add(YCPString("notify"), YCPBoolean(upgrade.notify()));
-             upgrades->add(YCPString("status"), YCPString(upgrade.status()));
-             upgrades->add(YCPString("product"), YCPString(upgrade.product()));
+               // add reference file in /etc/products.d
+               if (status.isInstalled() && (all || 
attrs->contains(YCPSymbol("upgrades"))))
+               {
+                       product_file = (_target_root + "/etc/products.d/" + 
product->referenceFilename()).asString();
+                       y2milestone("Parsing product file %s", 
product_file.c_str());
+                       const zypp::parser::ProductFileData productFileData = 
zypp::parser::ProductFileReader::scanFile(product_file);
 
-             upgrade_list->add(upgrades);
-           }
+                       YCPList upgrade_list;
 
-           info->add(YCPString("upgrades"), upgrade_list);
-       }
-       else
-       {
-           // get the package
-           zypp::sat::Solvable refsolvable = product->referencePackage();
+                       for (const auto &upgrade : productFileData.upgrades())
+                       {
+                               YCPMap upgrades;
+                               upgrades->add(YCPString("name"), 
YCPString(upgrade.name()));
+                               upgrades->add(YCPString("summary"), 
YCPString(upgrade.summary()));
+                               upgrades->add(YCPString("repository"), 
YCPString(upgrade.repository()));
+                               upgrades->add(YCPString("notify"), 
YCPBoolean(upgrade.notify()));
+                               upgrades->add(YCPString("status"), 
YCPString(upgrade.status()));
+                               upgrades->add(YCPString("product"), 
YCPString(upgrade.product()));
 
-           if (refsolvable != zypp::sat::Solvable::noSolvable)
-           {
-               // create a package pointer from the SAT solvable
-               zypp::Package::Ptr 
refpkg(zypp::make<zypp::Package>(refsolvable));
+                               upgrade_list->add(upgrades);
+                       }
 
-               if (refpkg)
+                       info->add(YCPString("upgrades"), upgrade_list);
+               }
+               else
                {
-                   info->add(YCPString("product_package"), 
YCPString(refpkg->name()));
+                       // get the package
+                       zypp::sat::Solvable refsolvable = 
product->referencePackage();
 
-                   // get the package files
-                   zypp::Package::FileList files( refpkg->filelist() );
-                   y2milestone("The reference package has %d files", 
files.size());
+                       if (refsolvable != zypp::sat::Solvable::noSolvable)
+                       {
+                               // create a package pointer from the SAT 
solvable
+                               zypp::Package::Ptr 
refpkg(zypp::make<zypp::Package>(refsolvable));
 
-                   zypp::str::smatch what;
-                   const zypp::str::regex 
product_file_regex("^/etc/products\\.d/(.*\\.prod)$");
+                               if (refpkg)
+                               {
+                                       info->add(YCPString("product_package"), 
YCPString(refpkg->name()));
+
+                                       // get the package files
+                                       zypp::Package::FileList files( 
refpkg->filelist() );
+                                       y2milestone("The reference package has 
%d files", files.size());
+
+                                       zypp::str::smatch what;
+                                       const zypp::str::regex 
product_file_regex("^/etc/products\\.d/(.*\\.prod)$");
+
+                                       // find the product file
+                                       for(const auto &f : files)
+                                       {
+                                               if (zypp::str::regex_match(f, 
what, product_file_regex))
+                                               {
+                                                       product_file = what[1];
+                                                       break;
+                                               }
+                                       }
+                               }
+               }
+               }
 
-                   // find the product file
-                   for_(iter, files.begin(), files.end())
-                   {
-                       if (zypp::str::regex_match(*iter, what, 
product_file_regex))
-                       {
-                           product_file = what[1];
-                           break;
-                       }
-                   }
+               if (all || attrs->contains(YCPSymbol("product_file")))
+               {
+                       if (product_file.empty())
+                               y2warning("The product file has not been 
found");
+                       else
+                               y2milestone("Found product file %s", 
product_file.c_str());
+
+                       ADD_NOT_EMPTY_STRING("product_file", product_file);
                }
-           }
        }
 
-       if (product_file.empty())
-       {
-           y2warning("The product file has not been found");
-       }
-       else
-       {
-           y2milestone("Found product file %s", product_file.c_str());
-           info->add(YCPString("product_file"), YCPString(product_file));
-       }
-    }
     // pattern specific info
-    else if ( req_kind == "pattern" ) {
        zypp::Pattern::constPtr pattern = 
zypp::asKind<zypp::Pattern>(item.resolvable());
-       info->add(YCPString("category"), YCPString(pattern->category()));
-       info->add(YCPString("user_visible"), 
YCPBoolean(pattern->userVisible()));
-       info->add(YCPString("default"), YCPBoolean(pattern->isDefault()));
-       info->add(YCPString("icon"), YCPString(pattern->icon().asString()));
-       info->add(YCPString("script"), YCPString(pattern->script().asString()));
-       info->add(YCPString("order"), YCPString(pattern->order()));
+    if (pattern) {
+               ADD_SYMBOL("kind", "pattern");
+
+               ADD_STRING("category", pattern->category());
+               ADD_BOOLEAN("user_visible", pattern->userVisible());
+
+               ADD_BOOLEAN("default", pattern->isDefault());
+               ADD_STRING("icon", pattern->icon().asString());
+               ADD_STRING("script", pattern->script().asString());
+               ADD_STRING("order", pattern->order());
     }
+
     // patch specific info
-    else if ( req_kind == "patch" )
-    {
        zypp::Patch::constPtr patch_ptr = 
zypp::asKind<zypp::Patch>(item.resolvable());
+       if (patch_ptr)
+       {
+               ADD_SYMBOL("kind", "patch");
+
+               ADD_BOOLEAN("interactive", patch_ptr->interactive());
+               ADD_BOOLEAN("reboot_needed", patch_ptr->rebootSuggested());
+               ADD_BOOLEAN("relogin_needed", patch_ptr->reloginSuggested());
+               ADD_BOOLEAN("affects_pkg_manager", 
patch_ptr->restartSuggested());
+               ADD_BOOLEAN("is_needed", item.isBroken());
 
-       info->add(YCPString("interactive"), 
YCPBoolean(patch_ptr->interactive()));
-       info->add(YCPString("reboot_needed"), 
YCPBoolean(patch_ptr->rebootSuggested()));
-       info->add(YCPString("relogin_needed"), 
YCPBoolean(patch_ptr->reloginSuggested()));
-       info->add(YCPString("affects_pkg_manager"), 
YCPBoolean(patch_ptr->restartSuggested()));
-       info->add(YCPString("is_needed"), YCPBoolean(item.isBroken()));
         // names and versions of packages, contained in the patch
-        YCPMap contents;
-        zypp::Patch::Contents c( patch_ptr->contents() );
-        for_( it, c.begin(), c.end() )
-        {
-          contents->add (YCPString (it->name()), YCPString 
(it->edition().c_str()));
-        }
-        info->add(YCPString("contents"), contents);
+               if (all || attrs->contains(YCPSymbol("contents")))
+               {
+                       YCPMap contents;
+                       for (const auto &res : patch_ptr->contents())
+                               contents->add (YCPString (res.name()), 
YCPString (res.edition().c_str()));
+                       info->add(YCPString("contents"), contents);
+               }
     }
 
     // dependency info
-    if (dependencies)
+    if (deps || attrs->contains(YCPSymbol("dependencies")))
     {
-       std::set<std::string> _kinds;
-       _kinds.insert("provides");
-       _kinds.insert("prerequires");
-       _kinds.insert("requires");
-       _kinds.insert("conflicts");
-       _kinds.insert("obsoletes");
-       _kinds.insert("recommends");
-       _kinds.insert("suggests");
-       _kinds.insert("enhances");
-       _kinds.insert("supplements");
-       YCPList ycpdeps;
-       YCPList rawdeps;
-       for (std::set<std::string>::const_iterator kind_it = _kinds.begin();
-           kind_it != _kinds.end(); ++kind_it)
-       {
-            zypp::Dep depkind(*kind_it);
+               std::set<std::string> _kinds = {
+                       "provides", "prerequires", "requires", "conflicts", 
"obsoletes",
+                       "recommends", "suggests", "enhances", "supplements"
+               };
+
+               YCPList ycpdeps;
+               YCPList rawdeps;
+               for (const auto &kind : _kinds)
+               {
+            zypp::Dep depkind(kind);
             zypp::Capabilities deps = item.resolvable()->dep(depkind);
 
             // add raw dependencies
-            for_(it, deps.begin(), deps.end())
+                       for (const auto &d : deps)
             {
                 YCPMap rawdep;
-                rawdep->add(YCPString(*kind_it), YCPString(it->asString()));
+                rawdep->add(YCPString(kind), YCPString(d.asString()));
                 rawdeps->add(rawdep);
             }
 
@@ -593,40 +551,32 @@
             for (zypp::sat::WhatProvides::const_iterator d = prv.begin(); d != 
prv.end(); ++d)
             {
                 if (d->kind().asString().empty() || d->name().empty())
-                {
                     y2debug("Empty kind or name: kind: %s, name: %s", 
d->kind().asString().c_str(), d->name().c_str());
-                }
                 else
                 {
                     YCPMap ycpdep;
                     ycpdep->add (YCPString ("res_kind"), YCPString 
(d->kind().asString()));
                     ycpdep->add (YCPString ("name"), YCPString (d->name()));
-                    ycpdep->add (YCPString ("dep_kind"), YCPString (*kind_it));
+                    ycpdep->add (YCPString ("dep_kind"), YCPString (kind));
 
                     if (!ycpdeps.contains(ycpdep))
-                    {
                         ycpdeps->add (ycpdep);
-                    }
                 }
             }
-       }
+               }
 
-       if (ycpdeps.size() > 0)
-       {
-           info->add (YCPString ("dependencies"), ycpdeps);
-       }
+               if (ycpdeps.size() > 0)
+                       info->add (YCPString ("dependencies"), ycpdeps);
 
-       if (rawdeps.size() > 0)
-       {
-           info->add (YCPString ("deps"), rawdeps);
-       }
+               if (rawdeps.size() > 0)
+                       info->add (YCPString ("deps"), rawdeps);
     }
 
     return info;
 }
 
 YCPValue
-PkgFunctions::ResolvablePropertiesEx(const YCPString& name, const YCPSymbol& 
kind_r, const YCPString& version, bool dependencies)
+PkgFunctions::ResolvablePropertiesEx(const YCPString& name, const YCPSymbol& 
kind_r, const YCPString& version, bool all_attrs, bool deps, const YCPList 
&attrs = YCPList())
 {
     zypp::Resolvable::Kind kind;
     std::string req_kind = kind_r->symbol ();
@@ -704,7 +654,7 @@
                             // check version if required
                             if (vers.empty() || vers == 
inst_it->resolvable()->edition().asString())
                             {
-                                ret->add(Resolvable2YCPMap(*inst_it, req_kind, 
dependencies));
+                                ret->add(Resolvable2YCPMap(*inst_it, 
all_attrs, deps, attrs));
                             }
                         }
                     }
@@ -717,7 +667,7 @@
                             // check version if required
                             if (vers.empty() || vers == 
avail_it->resolvable()->edition().asString())
                             {
-                                ret->add(Resolvable2YCPMap(*avail_it, 
req_kind, dependencies));
+                                ret->add(Resolvable2YCPMap(*avail_it, 
all_attrs, deps, attrs));
                             }
                         }
                     }
@@ -730,7 +680,7 @@
                     return YCPVoid();
                 }
             }
-       }
+               }
     }
     catch(const zypp::Exception &expt)
     {
@@ -748,16 +698,12 @@
        it != zypp::ResPool::instance().proxy().byKindEnd(kind);
        ++it)
     {
-       zypp::ui::Selectable::Fate fate = (*it)->fate();
+               zypp::ui::Selectable::Fate fate = (*it)->fate();
 
-       if (to_install && fate == zypp::ui::Selectable::TO_INSTALL)
-       {
-           return true;
-       }
-       else if (!to_install && fate == zypp::ui::Selectable::TO_DELETE)
-       {
-           return true;
-       }
+               if (to_install && fate == zypp::ui::Selectable::TO_INSTALL)
+                       return true;
+               else if (!to_install && fate == zypp::ui::Selectable::TO_DELETE)
+                       return true;
     }
 
     return false;
@@ -765,20 +711,28 @@
 
 /**
    @builtin IsAnyResolvable
-   @short Is there any resolvable in the requried state?
+   @short Is there any resolvable in the required state?
    @param symbol kind_r kind of resolvable, can be `product, `patch, `package, 
`pattern or `any for any kind of resolvable
    @param symbol status status of resolvable, can be `to_install or `to_remove
    @return boolean true if a resolvable with the requested status was found
+
+   **Obsolete**
+
+   This call is obsolete, use `AnyResolvable()` call instead, it has more 
filtering options.
+
 */
 YCPValue
 PkgFunctions::IsAnyResolvable(const YCPSymbol& kind_r, const YCPSymbol& status)
 {
+       y2warning("Pkg::IsAnyResolvable() is obsolete.");
+       y2warning("Use Pkg::AnyResolvable({kind: ..., status: ...}) instead.");
+
     zypp::Resolvable::Kind kind;
 
     if (kind_r.isNull() || status.isNull())
     {
-       y2error("Invalid nil parameter!");
-       return YCPVoid();
+               y2error("Invalid nil parameter!");
+               return YCPVoid();
     }
 
     std::string req_kind = kind_r->symbol ();
@@ -786,23 +740,23 @@
 
     if (stat_str != "to_install" && stat_str != "to_remove")
     {
-       y2error("Invalid status parameter: %s", stat_str.c_str());
-       return YCPVoid();
+               y2error("Invalid status parameter: %s", stat_str.c_str());
+               return YCPVoid();
     }
 
     bool to_install = stat_str == "to_install";
 
     if( req_kind == "product" ) {
-       kind = zypp::ResKind::product;
+               kind = zypp::ResKind::product;
     }
     else if ( req_kind == "patch" ) {
        kind = zypp::ResKind::patch;
     }
     else if ( req_kind == "package" ) {
-       kind = zypp::ResKind::package;
+               kind = zypp::ResKind::package;
     }
     else if ( req_kind == "pattern" ) {
-       kind = zypp::ResKind::pattern;
+               kind = zypp::ResKind::pattern;
     }
     else if ( req_kind == "any" ) {
        try
@@ -837,3 +791,215 @@
     }
 }
 
+// A custom filter for filtering the libzypp resolvables.
+struct ResolvableFilter
+{
+       // The constructor, convert the input filters into the internal
+       // structure to make the filtering process faster and simpler.
+       ResolvableFilter(const YCPMap &attributes, const PkgFunctions &pf)
+               : pkg(pf), check_repo(false), check_transact_by(false), 
check_vendor(false),
+               check_locked(false), check_on_system(false), 
check_license_confirmed(false),
+               medium_nr(-1)
+       {
+               YCPValue kind_symbol = attributes->value(YCPSymbol("kind"));
+               if (!kind_symbol.isNull() && kind_symbol->isSymbol())
+                       kind = kind_symbol->asSymbol()->symbol();
+
+               YCPValue name_value = attributes->value(YCPSymbol("name"));
+               if (!name_value.isNull() && name_value->isString())
+                       name = name_value->asString()->value();
+
+               YCPValue status_symbol = attributes->value(YCPSymbol("status"));
+               if (!status_symbol.isNull() && status_symbol->isSymbol())
+                       status_str = status_symbol->asSymbol()->symbol();
+
+               YCPValue source_value = attributes->value(YCPSymbol("source"));
+               if (!source_value.isNull() && source_value->isInteger()) {
+                       check_repo = true;
+                       repo = source_value->asInteger()->value();
+               }
+
+               YCPValue medium_nr_value = 
attributes->value(YCPSymbol("medium_nr"));
+               if (!medium_nr_value.isNull() && medium_nr_value->isInteger())
+                       medium_nr = medium_nr_value->asInteger()->value();
+
+               YCPValue transact_by_value = 
attributes->value(YCPSymbol("transact_by"));
+               if (!transact_by_value.isNull() && 
transact_by_value->isSymbol()) {
+                       check_transact_by = true;
+                       std::string transact_by_str = 
transact_by_value->asSymbol()->symbol();
+
+                       if (transact_by_str == "user")
+                               transact_by = zypp::ResStatus::USER;
+                       else if (transact_by_str == "app_high")
+                               transact_by = zypp::ResStatus::APPL_HIGH;
+                       else if (transact_by_str == "app_low")
+                               transact_by = zypp::ResStatus::APPL_LOW;
+                       else if (transact_by_str == "solver")
+                               transact_by = zypp::ResStatus::SOLVER;
+                       else {
+                               y2warning("Invalid 'transact_by' value: %s", 
transact_by_str.c_str());
+                               check_transact_by = false;
+                       }
+               }
+
+               YCPValue arch_value = attributes->value(YCPSymbol("arch"));
+               if (!arch_value.isNull() && arch_value->isString())
+                       arch_str = arch_value->asString()->value();
+
+               YCPValue version_value = 
attributes->value(YCPSymbol("version"));
+               if (!version_value.isNull() && version_value->isString())
+                       version_str = version_value->asString()->value();
+
+               YCPValue vendor_value = attributes->value(YCPSymbol("vendor"));
+               if (!vendor_value.isNull() && vendor_value->isString())
+               {
+                       check_vendor = true;
+                       vendor = vendor_value->asString()->value();
+               }
+
+               YCPValue locked_value = attributes->value(YCPSymbol("locked"));
+               if (!locked_value.isNull() && locked_value->isBoolean())
+               {
+                       check_locked = true;
+                       locked = vendor_value->asBoolean()->value();
+               }
+
+               YCPValue on_system_value = 
attributes->value(YCPSymbol("on_system_by_user"));
+               if (!on_system_value.isNull() && on_system_value->isBoolean())
+               {
+                       check_on_system = true;
+                       on_system = on_system_value->asBoolean()->value();
+               }
+
+               YCPValue license_confirmed_value = 
attributes->value(YCPSymbol("license_confirmed"));
+               if (!license_confirmed_value.isNull() && 
license_confirmed_value->isBoolean())
+               {
+                       check_license_confirmed = true;
+                       license_confirmed = 
license_confirmed_value->asBoolean()->value();
+               }
+       }
+
+       // The main filtering function, returns true/false for each resolvable 
in the pool
+       // whether it matches the required criteria.
+       bool operator()(const zypp::PoolItem &r) const
+       {
+               // check the kind
+               if (!kind.empty() && kind != r->kind())
+                       return false;
+
+               // check the name
+               if (!name.empty() && name != r->name())
+                       return false;
+
+               // check the version
+               if (!version_str.empty() && version_str != 
r->edition().asString())
+                       return false;
+
+               // check the architecture
+               if (!arch_str.empty() && arch_str != r->arch().asString())
+                       return false;
+
+               // check the vendor
+               if (check_vendor && vendor != r->vendor())
+                       return false;
+
+               // check the lock status
+               if (check_locked && locked != r.status().isLocked())
+                       return false;
+
+               // check the license status
+               if (check_license_confirmed && license_confirmed != 
r.status().isLicenceConfirmed())
+                       return false;
+
+               // check the status
+               if (!status_str.empty()) {
+                       zypp::ResStatus status = r.status();
+
+                       if (!status.isToBeInstalled() && status_str == 
"selected")
+                               return false;
+                       if (!status.isToBeUninstalled() && status_str == 
"removed")
+                               return false;
+                       if (!(status.isInstalled() || status.isSatisfied()) && 
status_str == "installed")
+                               return false;
+                       // otherwise the resolvable has status available
+                       if ((status.isToBeInstalled() || status.isInstalled() 
|| status.isSatisfied()) && status_str == "available")
+                               return false;
+               }
+
+               // check who changed the status
+               if (check_transact_by && r.status().getTransactByValue() != 
transact_by)
+                       return false;
+
+               // check the repository
+               if (check_repo && pkg.logFindAlias(r->repoInfo().alias()) != 
repo)
+                       return false;
+
+               // check if on system by user
+               if (check_on_system && on_system != 
r.satSolvable().onSystemByUser())
+                       return false;
+
+               // check the medium number
+               if (medium_nr >= 0 && medium_nr != r->mediaNr())
+                       return false;
+
+               return true;
+       }
+
+       // reference to PkgFunctions, we need to call 
PkgFunctions::logFindAlias()
+       const PkgFunctions &pkg;
+
+       std::string kind, name, status_str, transact_by_str, arch_str, 
version_str;
+
+       bool check_repo;
+       PkgFunctions::RepoId repo;
+
+       bool check_transact_by;
+       zypp::ResStatus::TransactByValue transact_by;
+
+       bool check_vendor;
+       std::string vendor;
+
+       bool check_locked, locked;
+       bool check_on_system, on_system;
+       bool check_license_confirmed, license_confirmed;
+       long long medium_nr;
+};
+
+/**
+   @builtin Resolvables
+   @short Is there any resolvable matching the input filter?
+   @param map filter
+   @param list attrs the list of required attributes
+   @return boolean true if a resolvable was found, false otherwise
+
+   See the ResolvableProperties() call for the accepted filtering keys
+   and returned attributes.
+*/
+YCPValue PkgFunctions::Resolvables(const YCPMap& filter, const YCPList& attrs)
+{
+       if (attrs.isEmpty())
+               y2warning("Passed empty attribute list, empty maps will be 
returned");
+
+       YCPList ret;
+
+       for (const auto &r : 
zypp::ResPool::instance().filter(ResolvableFilter(filter, *this)) )
+               ret->add(Resolvable2YCPMap(r, false, false, attrs));
+
+       return ret;
+}
+
+/**
+   @builtin AnyResolvable
+   @short Is there any resolvable matching the input filter?
+   @param map filter
+   @return boolean true if a resolvable was found, false otherwise
+
+   See the ResolvableProperties() call for the accepted filtering keys.
+*/
+YCPValue PkgFunctions::AnyResolvable(const YCPMap& filter)
+{
+       for (const auto &r : 
zypp::ResPool::instance().filter(ResolvableFilter(filter, *this)) )
+               return YCPBoolean(true);
+
+       return YCPBoolean(false);
+}


Reply via email to