summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:40:49 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:40:49 +0900
commitc948f862b552adbe2cdee24096357b887dfbb088 (patch)
treeb25b1ac6fc699b94972c9f1cf697a0c679cd02a5
parente1659dc4ce74d3c47f465103951dafff8fc0cf9f (diff)
downloadlibsolv-c948f862b552adbe2cdee24096357b887dfbb088.tar.gz
libsolv-c948f862b552adbe2cdee24096357b887dfbb088.tar.bz2
libsolv-c948f862b552adbe2cdee24096357b887dfbb088.zip
Imported Upstream version 0.6.29upstream/0.6.29
Change-Id: I9bac0213cb8a171344b94297e08c1c52595c0abe Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
-rw-r--r--NEWS5
-rw-r--r--TODO_1.034
-rw-r--r--VERSION.cmake2
-rw-r--r--bindings/python/CMakeLists.txt7
-rw-r--r--bindings/solv.i19
-rw-r--r--doc/CMakeLists.txt4
-rw-r--r--doc/Makefile.gen8
-rw-r--r--doc/appdata2solv.txt4
-rw-r--r--doc/archpkgs2solv.txt4
-rw-r--r--doc/archrepo2solv.txt4
-rw-r--r--doc/comps2solv.txt4
-rw-r--r--doc/deb2solv.txt4
-rw-r--r--doc/deltainfoxml2solv.txt4
-rw-r--r--doc/dumpsolv.txt4
-rw-r--r--doc/gen/appdata2solv.1 (renamed from doc/appdata2solv.1)6
-rw-r--r--doc/gen/archpkgs2solv.1 (renamed from doc/archpkgs2solv.1)6
-rw-r--r--doc/gen/archrepo2solv.1 (renamed from doc/archrepo2solv.1)6
-rw-r--r--doc/gen/comps2solv.1 (renamed from doc/comps2solv.1)6
-rw-r--r--doc/gen/deb2solv.1 (renamed from doc/deb2solv.1)6
-rw-r--r--doc/gen/deltainfoxml2solv.1 (renamed from doc/deltainfoxml2solv.1)6
-rw-r--r--doc/gen/dumpsolv.1 (renamed from doc/dumpsolv.1)6
-rw-r--r--doc/gen/helix2solv.1 (renamed from doc/helix2solv.1)6
-rw-r--r--doc/gen/installcheck.1 (renamed from doc/installcheck.1)6
-rw-r--r--doc/gen/libsolv-bindings.3 (renamed from doc/libsolv-bindings.3)60
-rw-r--r--doc/gen/libsolv-constantids.3 (renamed from doc/libsolv-constantids.3)6
-rw-r--r--doc/gen/libsolv-history.3 (renamed from doc/libsolv-history.3)6
-rw-r--r--doc/gen/libsolv-pool.3 (renamed from doc/libsolv-pool.3)49
-rw-r--r--doc/gen/libsolv.3 (renamed from doc/libsolv.3)6
-rw-r--r--doc/gen/mdk2solv.1 (renamed from doc/mdk2solv.1)6
-rw-r--r--doc/gen/mergesolv.1 (renamed from doc/mergesolv.1)6
-rw-r--r--doc/gen/repomdxml2solv.1 (renamed from doc/repomdxml2solv.1)6
-rw-r--r--doc/gen/rpmdb2solv.1 (renamed from doc/rpmdb2solv.1)6
-rw-r--r--doc/gen/rpmmd2solv.1 (renamed from doc/rpmmd2solv.1)6
-rw-r--r--doc/gen/rpms2solv.1 (renamed from doc/rpms2solv.1)6
-rw-r--r--doc/gen/susetags2solv.1 (renamed from doc/susetags2solv.1)6
-rw-r--r--doc/gen/testsolv.1 (renamed from doc/testsolv.1)6
-rw-r--r--doc/gen/updateinfoxml2solv.1 (renamed from doc/updateinfoxml2solv.1)6
-rw-r--r--doc/helix2solv.txt4
-rw-r--r--doc/installcheck.txt4
-rw-r--r--doc/libsolv-bindings.txt45
-rw-r--r--doc/libsolv-constantids.txt3
-rw-r--r--doc/libsolv-history.txt4
-rw-r--r--doc/libsolv-pool.txt58
-rw-r--r--doc/libsolv.txt3
-rw-r--r--doc/mdk2solv.txt4
-rw-r--r--doc/mergesolv.txt4
-rw-r--r--doc/repomdxml2solv.txt4
-rw-r--r--doc/rpmdb2solv.txt4
-rw-r--r--doc/rpmmd2solv.txt4
-rw-r--r--doc/rpms2solv.txt4
-rw-r--r--doc/susetags2solv.txt4
-rw-r--r--doc/testsolv.txt4
-rw-r--r--doc/updateinfoxml2solv.txt4
-rw-r--r--examples/solv/deltarpm.c4
-rw-r--r--examples/solv/repoinfo.c10
-rw-r--r--examples/solv/repoinfo_config_yum.c10
-rw-r--r--examples/solv/repoinfo_download.c5
-rw-r--r--examples/solv/solv.c10
-rw-r--r--ext/pool_parserpmrichdep.c13
-rw-r--r--ext/repo_rpmdb.c36
-rw-r--r--ext/repo_susetags.c393
-rw-r--r--ext/testcase.c2
-rw-r--r--package/libsolv.changes11
-rw-r--r--src/cplxdeps.c404
-rw-r--r--src/cplxdeps.h7
-rw-r--r--src/policy.c4
-rw-r--r--src/pool.c35
-rw-r--r--src/pool.h11
-rw-r--r--src/poolid.c10
-rw-r--r--src/rules.c3
-rw-r--r--src/selection.c6
-rw-r--r--src/solver.c75
-rw-r--r--src/solver_private.h31
-rw-r--r--test/testcases/cplxdeps/and.t39
-rw-r--r--test/testcases/cplxdeps/andor.t73
-rw-r--r--test/testcases/cplxdeps/if.t36
-rw-r--r--test/testcases/cplxdeps/ifelse.t70
-rw-r--r--test/testcases/cplxdeps/or.t34
-rw-r--r--test/testcases/cplxdeps/orand.t87
-rw-r--r--test/testcases/recommendations/recommended_conflicts.t16
-rw-r--r--test/testcases/recommendations/recommended_multirepo.t19
-rw-r--r--test/testcases/recommendations/recommended_oldversion.t15
-rw-r--r--test/testcases/recommendations/recommended_targeted.t15
-rw-r--r--test/testcases/recommendations/recommended_version.t15
-rw-r--r--test/testcases/recommendations/suggested_conflicts.t16
-rw-r--r--test/testcases/recommendations/suggested_multirepo.t19
-rw-r--r--test/testcases/recommendations/suggested_oldversion.t15
-rw-r--r--test/testcases/recommendations/suggested_targeted.t15
-rw-r--r--test/testcases/recommendations/suggested_version.t15
89 files changed, 1449 insertions, 629 deletions
diff --git a/NEWS b/NEWS
index b3fd37b..396bfdb 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@
This file contains the major changes between
libsolv versions:
+Version 0.6.29
+- new features:
+ * support for REL_WITHOUT and REL_UNLESS dependencies
+ * solver_get_recommendations available in bindings
+
Version 0.6.28
- new features:
* new pool_best_solvables() function
diff --git a/TODO_1.0 b/TODO_1.0
new file mode 100644
index 0000000..cb5055d
--- /dev/null
+++ b/TODO_1.0
@@ -0,0 +1,34 @@
+
+- make dataiterator only return the last occurance of a key
+
+- implement package priority (for things like Debian's pin feature)
+
+- merge SUSETAGS_FILE_* and REPOSITORY_REPOMD_* keys into REPOSITORY_RESOURCE
+
+- re-order key ids
+
+- deal with DIRSTR entries having dirid 0 (for source rpms)
+
+- test rich dep rule creation
+
+- clean up rich dep rule code (see perl-BSSolv)
+
+- drop patchcheck
+
+- rename repo2solv.sh to repo2solv (maybe rewrite in C?)
+
+- obey -A option in repo2solv
+
+- make FAVOR handling deal with versions
+
+- write more manpages
+
+- use dup rules all the time
+
+- bindings: selections.flags() should be a attribute and not a method
+
+- rename repodata_lookup_id_uninternalized to repodata_lookup_id_voidid_uninternalized
+ and add a notfound argument
+
+IDEAS:
+
diff --git a/VERSION.cmake b/VERSION.cmake
index f4958cb..f24ed63 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "0")
SET(LIBSOLV_MAJOR "0")
SET(LIBSOLV_MINOR "6")
-SET(LIBSOLV_PATCH "28")
+SET(LIBSOLV_PATCH "29")
diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt
index a83695f..64ef528 100644
--- a/bindings/python/CMakeLists.txt
+++ b/bindings/python/CMakeLists.txt
@@ -6,7 +6,12 @@ IF (ENABLE_PYTHON3 AND NOT DEFINED PythonLibs_FIND_VERSION)
ENDIF (ENABLE_PYTHON3 AND NOT DEFINED PythonLibs_FIND_VERSION)
FIND_PACKAGE (PythonLibs REQUIRED)
-FIND_PACKAGE (PythonInterp ${PYTHONLIBS_VERSION_STRING} REQUIRED)
+IF(PYTHONLIBS_VERSION_STRING MATCHES "^([0-9.]+)")
+ SET(python_version "${CMAKE_MATCH_1}")
+ELSE()
+ MESSAGE(FATAL_ERROR "PythonLibs version format unknown '${PYTHONLIBS_VERSION_STRING}'")
+ENDIF()
+FIND_PACKAGE (PythonInterp ${python_version} REQUIRED)
EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c "from sys import stdout; from distutils import sysconfig; stdout.write(sysconfig.get_python_lib(True))" OUTPUT_VARIABLE PYTHON_INSTALL_DIR)
diff --git a/bindings/solv.i b/bindings/solv.i
index 354cde7..6313d9b 100644
--- a/bindings/solv.i
+++ b/bindings/solv.i
@@ -946,6 +946,8 @@ typedef int Id;
%constant int REL_MULTIARCH;
%constant int REL_ELSE;
%constant int REL_ERROR;
+%constant int REL_WITHOUT;
+%constant int REL_UNLESS;
typedef struct {
Pool* const pool;
@@ -3512,6 +3514,23 @@ rb_eval_string(
}
return q;
}
+
+ %typemap(out) Queue get_recommended Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+ %newobject get_recommended;
+ Queue get_recommended(bool noselected=0) {
+ Queue q;
+ queue_init(&q);
+ solver_get_recommendations($self, &q, NULL, noselected);
+ return q;
+ }
+ %typemap(out) Queue get_suggested Queue2Array(XSolvable *, 1, new_XSolvable(arg1->pool, id));
+ %newobject get_suggested;
+ Queue get_suggested(bool noselected=0) {
+ Queue q;
+ queue_init(&q);
+ solver_get_recommendations($self, NULL, &q, noselected);
+ return q;
+ }
}
%extend Transaction {
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 13e086c..b18596d 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -42,6 +42,10 @@ IF (ENABLE_APPDATA)
SET (libsolv_MANPAGES1 ${libsolv_MANPAGES1} appdata2solv.1)
ENDIF (ENABLE_APPDATA)
+# prepend gen directory
+STRING(REGEX REPLACE "([^;]+)" "gen/\\1" libsolv_MANPAGES1 "${libsolv_MANPAGES1}")
+STRING(REGEX REPLACE "([^;]+)" "gen/\\1" libsolv_MANPAGES3 "${libsolv_MANPAGES3}")
+
INSTALL(FILES
${libsolv_MANPAGES3}
DESTINATION "${MAN_INSTALL_DIR}/man3")
diff --git a/doc/Makefile.gen b/doc/Makefile.gen
index 84a1095..2e8c4a1 100644
--- a/doc/Makefile.gen
+++ b/doc/Makefile.gen
@@ -1,4 +1,6 @@
+VPATH = gen
+
man: man3 man1
man3: libsolv.3 libsolv-bindings.3 libsolv-constantids.3 libsolv-history.3 libsolv-pool.3
@@ -13,10 +15,10 @@ html: libsolv.html libsolv-bindings.html libsolv-constantids.html libsolv-histor
.SUFFIXES: .html .3 .1 .txt
.txt.1:
- a2x -f manpage $<
+ a2x -f manpage -D gen $<
.txt.3:
- a2x -f manpage $<
+ a2x -f manpage -D gen $<
.txt.html:
- a2x -f xhtml $<
+ a2x -f xhtml -D gen $<
diff --git a/doc/appdata2solv.txt b/doc/appdata2solv.txt
index 3ccb4b5..c31311a 100644
--- a/doc/appdata2solv.txt
+++ b/doc/appdata2solv.txt
@@ -37,3 +37,7 @@ mergesolv(1)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/archpkgs2solv.txt b/doc/archpkgs2solv.txt
index 2a17066..4ce3155 100644
--- a/doc/archpkgs2solv.txt
+++ b/doc/archpkgs2solv.txt
@@ -33,3 +33,7 @@ pacman(8)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/archrepo2solv.txt b/doc/archrepo2solv.txt
index 3f5b138..1a7791c 100644
--- a/doc/archrepo2solv.txt
+++ b/doc/archrepo2solv.txt
@@ -29,3 +29,7 @@ pacman(8)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/comps2solv.txt b/doc/comps2solv.txt
index 23e304e..8d98708 100644
--- a/doc/comps2solv.txt
+++ b/doc/comps2solv.txt
@@ -27,3 +27,7 @@ mergesolv(1), createrepo(8)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/deb2solv.txt b/doc/deb2solv.txt
index 0907383..cb42ff7 100644
--- a/doc/deb2solv.txt
+++ b/doc/deb2solv.txt
@@ -33,3 +33,7 @@ deb(5), dpkg-deb(1)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/deltainfoxml2solv.txt b/doc/deltainfoxml2solv.txt
index f14a843..13c987d 100644
--- a/doc/deltainfoxml2solv.txt
+++ b/doc/deltainfoxml2solv.txt
@@ -27,3 +27,7 @@ mergesolv(1), createrepo(8)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/dumpsolv.txt b/doc/dumpsolv.txt
index ec2d771..b09aa97 100644
--- a/doc/dumpsolv.txt
+++ b/doc/dumpsolv.txt
@@ -24,3 +24,7 @@ Write the contents in JSON format.
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/appdata2solv.1 b/doc/gen/appdata2solv.1
index b5fdf9f..4fe217d 100644
--- a/doc/appdata2solv.1
+++ b/doc/gen/appdata2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: appdata2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 07/25/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "APPDATA2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "APPDATA2SOLV" "1" "07/25/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/archpkgs2solv.1 b/doc/gen/archpkgs2solv.1
index 6052aee..bb47364 100644
--- a/doc/archpkgs2solv.1
+++ b/doc/gen/archpkgs2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: archpkgs2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 07/25/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "ARCHPKGS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "ARCHPKGS2SOLV" "1" "07/25/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/archrepo2solv.1 b/doc/gen/archrepo2solv.1
index 94f5c41..9d7c868 100644
--- a/doc/archrepo2solv.1
+++ b/doc/gen/archrepo2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: archrepo2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 07/25/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "ARCHREPO2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "ARCHREPO2SOLV" "1" "07/25/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/comps2solv.1 b/doc/gen/comps2solv.1
index c6f8d32..2be0bc9 100644
--- a/doc/comps2solv.1
+++ b/doc/gen/comps2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: comps2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 07/25/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "COMPS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "COMPS2SOLV" "1" "07/25/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/deb2solv.1 b/doc/gen/deb2solv.1
index 95f5091..7da3828 100644
--- a/doc/deb2solv.1
+++ b/doc/gen/deb2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: deb2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 07/25/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "DEB2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "DEB2SOLV" "1" "07/25/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/deltainfoxml2solv.1 b/doc/gen/deltainfoxml2solv.1
index 11cda74..0ef0bb4 100644
--- a/doc/deltainfoxml2solv.1
+++ b/doc/gen/deltainfoxml2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: deltainfoxml2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 07/25/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "DELTAINFOXML2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "DELTAINFOXML2SOLV" "1" "07/25/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/dumpsolv.1 b/doc/gen/dumpsolv.1
index cb6a136..eed45fe 100644
--- a/doc/dumpsolv.1
+++ b/doc/gen/dumpsolv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: dumpsolv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 07/25/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "DUMPSOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "DUMPSOLV" "1" "07/25/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/helix2solv.1 b/doc/gen/helix2solv.1
index 07d9497..dacc5fe 100644
--- a/doc/helix2solv.1
+++ b/doc/gen/helix2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: helix2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 12/14/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "HELIX2SOLV" "1" "12/14/2015" "libsolv" "LIBSOLV"
+.TH "HELIX2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/installcheck.1 b/doc/gen/installcheck.1
index 7ee3e4d..7965f00 100644
--- a/doc/installcheck.1
+++ b/doc/gen/installcheck.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: installcheck
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "INSTALLCHECK" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "INSTALLCHECK" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/libsolv-bindings.3 b/doc/gen/libsolv-bindings.3
index f2d8e8d..7350224 100644
--- a/doc/libsolv-bindings.3
+++ b/doc/gen/libsolv-bindings.3
@@ -2,12 +2,12 @@
.\" Title: Libsolv-Bindings
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 12/14/2016
+.\" Date: 09/07/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-BINDINGS" "3" "12/14/2016" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-BINDINGS" "3" "09/07/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -2070,9 +2070,9 @@ Add the contents of the mageia/mandriva repository metadata (the "synthesis\&.hd
.\}
.nf
\fBbool add_mdk_info(FILE *\fR\fIfp\fR\fB, int\fR \fIflags\fR \fB= 0)\fR
-\fI$repo\fR\fB\->add_mdk(\fR\fI$fp\fR\fB)\fR;
-\fIrepo\fR\fB\&.add_mdk(\fR\fIfp\fR\fB)\fR
-\fIrepo\fR\fB\&.add_mdk(\fR\fIfp\fR\fB)\fR
+\fI$repo\fR\fB\->add_mdk_info(\fR\fI$fp\fR\fB)\fR;
+\fIrepo\fR\fB\&.add_mdk_info(\fR\fIfp\fR\fB)\fR
+\fIrepo\fR\fB\&.add_mdk_info(\fR\fIfp\fR\fB)\fR
.fi
.if n \{\
.RE
@@ -2426,9 +2426,9 @@ Return a tuple containing the on\-media location and an optional media number fo
.\}
.nf
\fBconst char *lookup_sourcepkg()\fR;
-my \fR\fI$sourcepkg\fR\fB =\fR \fI$solvable\fR\fB\->lookup_sourcepkg()\fR;
-\fIsourcepkg\fR\fB \fB=\fR \fIsolvable\fR\fB\&.lookup_sourcepkg()\fR
-\fIsourcepkg\fR\fB \fB=\fR \fIsolvable\fR\fB\&.lookup_sourcepkg()\fR
+my \fI$sourcepkg\fR \fB=\fR \fI$solvable\fR\fB\->lookup_sourcepkg()\fR;
+\fIsourcepkg\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_sourcepkg()\fR
+\fIsourcepkg\fR \fB=\fR \fIsolvable\fR\fB\&.lookup_sourcepkg()\fR
.fi
.if n \{\
.RE
@@ -2566,7 +2566,7 @@ Returns \-1 if the epoch/version/release of the solvable is less than the one fr
.RE
.\}
.sp
-Return true if the dependencies stored in keyname match the specified dependeny\&.
+Return true if the dependencies stored in keyname match the specified dependency\&.
.sp
.if n \{\
.RS 4
@@ -3561,7 +3561,7 @@ If multiple packages obsolete an installed package, the solver checks the provid
.PP
\fBSOLVER_FLAG_NEED_UPDATEPROVIDE\fR
.RS 4
-This is somewhat the opposite of SOLVER_FLAG_NO_UPDATEPROVIDE: Only packages that provied the installed package names are considered for updating\&.
+This is somewhat the opposite of SOLVER_FLAG_NO_UPDATEPROVIDE: Only packages that provide the installed package names are considered for updating\&.
.RE
.PP
\fBSOLVER_FLAG_SPLITPROVIDES\fR
@@ -3968,6 +3968,36 @@ my \fB(\fR\fI$reason\fR\fB,\fR \fI$rule\fR\fB) =\fR \fI$solver\fR\fB\->describe_
.\}
.sp
Return the reason why a specific solvable was installed or erased\&. For most of the reasons the rule that triggered the decision is also returned\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBSolvable *get_recommended(bool\fR \fInoselected\fR\fB=0)\fR;
+my \fI@solvables\fR \fB=\fR \fI$solver\fR\fB\->get_recommended()\fR;
+\fIsolvables\fR \fB=\fR \fIsolver\fR\fB\&.get_recommended()\fR
+\fIsolvables\fR \fB=\fR \fIsolver\fR\fB\&.get_recommended()\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Return all solvables that are recommended by the solver run result\&. This includes solvables included in the result, set noselected if you want to filter those\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\fBSolvable *get_suggested(bool\fR \fInoselected\fR\fB=0)\fR;
+my \fI@solvables\fR \fB=\fR \fI$solver\fR\fB\->get_suggested()\fR;
+\fIsolvables\fR \fB=\fR \fIsolver\fR\fB\&.get_suggested()\fR
+\fIsolvables\fR \fB=\fR \fIsolver\fR\fB\&.get_suggested()\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Return all solvables that are suggested by the solver run result\&. This includes solvables included in the result, set noselected if you want to filter those\&.
.SH "THE PROBLEM CLASS"
.sp
Problems are the way of the solver to interact with the user\&. You can simply list all problems and terminate your program, but a better way is to present solutions to the user and let him pick the ones he likes\&.
@@ -4025,8 +4055,8 @@ Return the rule that caused the problem\&. Of course in most situations there is
.nf
\fBRule *findallproblemrules(bool\fR \fIunfiltered\fR \fB= 0)\fR
my \fI@probrules\fR \fB=\fR \fI$problem\fR\fB\->findallproblemrules()\fR;
-\fIprobrules\fR \fB=\fR \fIproblem\fR\fB\&.findallproblemrule()\fR
-\fIprobrules\fR \fB=\fR \fIproblem\fR\fB\&.findallproblemrule()\fR
+\fIprobrules\fR \fB=\fR \fIproblem\fR\fB\&.findallproblemrules()\fR
+\fIprobrules\fR \fB=\fR \fIproblem\fR\fB\&.findallproblemrules()\fR
.fi
.if n \{\
.RE
@@ -4531,7 +4561,7 @@ my \fI$job\fR \fB=\fR \fI$solutionelement\fR\fB\->Job()\fR;
.RE
.\}
.sp
-Create a job that implements the solution element\&. Add this job to the array of jobs for all elements of type different to SOLVER_SOLUTION_JOB and SOLVER_SOLUTION_POOLJOB\&. For the later two, a SOLVER_NOOB Job is created, you should replace the old job with the new one\&.
+Create a job that implements the solution element\&. Add this job to the array of jobs for all elements of type different to SOLVER_SOLUTION_JOB and SOLVER_SOLUTION_POOLJOB\&. For the latter two, a SOLVER_NOOB Job is created, you should replace the old job with the new one\&.
.sp
.if n \{\
.RS 4
@@ -5456,7 +5486,7 @@ Create stub repodatas from the information stored in the repodata meta area\&.
.RE
.\}
.sp
-Extend the repodata so that it has the same size as the repo it belongs to\&. This method is only needed when switching to a just written repodata extension to make the repodata match the written extension (which is always of the size of the repo)\&.
+Extend the repodata so that it has the same size as the repo it belongs to\&. This method is needed when setting up a new extension repodata so that it matches the repository size\&. It is also needed when switching to a just written repodata extension to make the repodata match the written extension (which is always of the size of the repo)\&.
.sp
.if n \{\
.RS 4
@@ -5573,7 +5603,7 @@ Lookup functions\&. Return the data element stored in the specified solvable\&.
.\}
.nf
\fBvoid set_sourcepkg(Id\fR \fIsolvid\fR\fB, const char *\fR\fIsourcepkg\fR\fB)\fR;
-\fI$data\fR\fB\->set_sourcepkg(\fR\fI$solvid\fR\fB, \fI$sourcepkg\fR\fB)\fR;
+\fI$data\fR\fB\&.set_sourcepkg(\fR\fI$solvid\fR\fB,\fR \fI$sourcepkg\fR\fB)\fR;
\fIdata\fR\fB\&.set_sourcepkg(\fR\fIsolvid\fR\fB,\fR \fIsourcepkg\fR\fB)\fR
\fIdata\fR\fB\&.set_sourcepkg(\fR\fIsolvid\fR\fB,\fR \fIsourcepkg\fR\fB)\fR
.fi
diff --git a/doc/libsolv-constantids.3 b/doc/gen/libsolv-constantids.3
index 327150c..87a14e6 100644
--- a/doc/libsolv-constantids.3
+++ b/doc/gen/libsolv-constantids.3
@@ -1,13 +1,13 @@
'\" t
.\" Title: Libsolv-Constantids
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 12/14/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-CONSTANTIDS" "3" "12/14/2015" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-CONSTANTIDS" "3" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/libsolv-history.3 b/doc/gen/libsolv-history.3
index 872cd4e..6a600ac 100644
--- a/doc/libsolv-history.3
+++ b/doc/gen/libsolv-history.3
@@ -1,13 +1,13 @@
'\" t
.\" Title: Libsolv-History
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-HISTORY" "3" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-HISTORY" "3" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/libsolv-pool.3 b/doc/gen/libsolv-pool.3
index adc13e3..d324f68 100644
--- a/doc/libsolv-pool.3
+++ b/doc/gen/libsolv-pool.3
@@ -1,13 +1,13 @@
'\" t
.\" Title: Libsolv-Pool
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 05/06/2016
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 09/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-POOL" "3" "05/06/2016" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-POOL" "3" "09/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -608,10 +608,35 @@ An internal file conflict dependency used to represent file conflicts\&. See the
A conditional dependency, the \(lqname\(rq sub\-dependency is only considered if the \(lqevr\(rq sub\-dependency is fulfilled\&. See the section about boolean dependencies about more information\&.
.RE
.PP
+\fBREL_UNLESS\fR
+.RS 4
+A conditional dependency, the \(lqname\(rq sub\-dependency is only considered if the \(lqevr\(rq sub\-dependency is not fulfilled\&. See the section about boolean dependencies about more information\&.
+.RE
+.PP
\fBREL_COMPAT\fR
.RS 4
A compat dependency used in Haiku to represent version ranges\&. The \(lqname\(rq part is the actual version, the \(lqevr\(rq part is the backwards compatibility version\&.
.RE
+.PP
+\fBREL_KIND\fR
+.RS 4
+A pseudo dependency that limits the solvables to a specific kind\&. The kind is expected to be a prefix of the solvable name, e\&.g\&. \(lqpatch:foo\(rq would be of kind \(lqpatch\(rq\&. \(lqREL_KIND\(rq is only supported in the selection functions\&.
+.RE
+.PP
+\fBREL_MULTIARCH\fR
+.RS 4
+A debian multiarch annotation\&. The most common value for the \(lqevr\(rq part is \(lqany\(rq\&.
+.RE
+.PP
+\fBREL_ELSE\fR
+.RS 4
+The else part of a \(lqREL_COND\(rq or \(lqREL_UNLESS\(rq dependency\&. See the section about boolean dependencies\&.
+.RE
+.PP
+\fBREL_ERROR\fR
+.RS 4
+An illegal dependency\&. This is useful to encode dependency parse errors\&.
+.RE
.SS "Functions"
.sp
.if n \{\
@@ -1241,7 +1266,7 @@ There can be multiple equivalence classes, the set of allowed vendor changes for
You can turn off the architecture replacement checks with the Solver\(cqs SOLVER_FLAG_ALLOW_VENDORCHANGE flag\&.
.SH "BOOLEAN DEPENDENCIES"
.sp
-Boolean Dependencies allow to build complex expressions from simple dependencies\&. While rpm does not support boolean expressions in dependencies and debian only allows an "OR" expression, libsolv allows arbitrary complex expressions\&. The following basic types are supported:
+Boolean Dependencies allow to build complex expressions from simple dependencies\&. Note that depending on the package manager only a subset of those may be useful\&. For example, debian currently only allows an "OR" expression\&.
.PP
\fBREL_OR\fR
.RS 4
@@ -1250,17 +1275,27 @@ The expression is true if either the first dependency or the second one is true\
.PP
\fBREL_AND\fR
.RS 4
-The expression is true if both dependencies are true\&. The packages fulfilling the dependencies may be different, i\&.e\&. \(lqSupplements: perl AND python\(rq is true if both a package providing perl and a package providing python are installed\&. The solver currently only supports REL_AND in Supplements/Enhances dependencies, in other types of dependencies it gets treated as REL_WITH\&.
+The expression is true if both dependencies are true\&. The packages fulfilling the dependencies may be different, i\&.e\&. \(lqSupplements: perl REL_AND python\(rq is true if both a package providing perl and a package providing python are installed\&.
.RE
.PP
\fBREL_WITH\fR
.RS 4
-The expression is true if both dependencies are true and are fulfilled by the same package\&. Thus \(lqSupplements: perl AND python\(rq would only be true if a package is installed that provides both dependencies (some kind of multi\-language interpreter)\&.
+The expression is true if both dependencies are true and are fulfilled by the same package\&. Thus \(lqSupplements: perl REL_WITH python\(rq would only be true if a package is installed that provides both dependencies (some kind of multi\-language interpreter)\&.
.RE
.PP
\fBREL_COND\fR
.RS 4
-The expression is true if the first dependency is true or the second dependency is false\&. Libsolv currently does not support this type of dependency in the solver code\&.
+The expression is true if the first dependency is true or the second dependency is false\&. \(lqA REL_COND B\(rq is equivalent to \(lqA REL_OR (NOT B)\(rq (except that libsolv does not expose \(lqNOT\(rq)\&.
+.RE
+.PP
+\fBREL_UNLESS\fR
+.RS 4
+The expression is true if the first dependency is true and the second dependency is false\&. \(lqA REL_UNLESS B\(rq is equivalent to \(lqA REL_AND (NOT B)\(rq (except that libsolv does not expose \(lqNOT\(rq)\&.
+.RE
+.PP
+\fBREL_ELSE\fR
+.RS 4
+The \(lqelse\(rq part of a \(lqREL_COND\(rq or \(lqREL_UNLESS\(rq dependency\&. It has to be directly in the evr part of the condition, e\&.g\&. \(lqfoo REL_COND (bar REL_ELSE baz)\(rq\&. For \(lqREL_COND\(rq this is equivalent to writing \(lq(foo REL_COND bar) REL_AND (bar REL_OR baz)\(rq\&. For \(lqREL_UNLESS\(rq this is equivalent to writing \(lq(foo REL_UNLESS bar) REL_OR (bar REL_AND baz)\(rq\&.
.RE
.sp
Each sub\-dependency of a boolean dependency can in turn be a boolean dependency, so you can chain them to create complex dependencies\&.
diff --git a/doc/libsolv.3 b/doc/gen/libsolv.3
index 24ab788..dcebb02 100644
--- a/doc/libsolv.3
+++ b/doc/gen/libsolv.3
@@ -1,13 +1,13 @@
'\" t
.\" Title: Libsolv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV" "3" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "LIBSOLV" "3" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/mdk2solv.1 b/doc/gen/mdk2solv.1
index 4400c9b..513187a 100644
--- a/doc/mdk2solv.1
+++ b/doc/gen/mdk2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: mdk2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "MDK2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "MDK2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/mergesolv.1 b/doc/gen/mergesolv.1
index 3ff00e8..1c706c7 100644
--- a/doc/mergesolv.1
+++ b/doc/gen/mergesolv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: mergesolv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "MERGESOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "MERGESOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/repomdxml2solv.1 b/doc/gen/repomdxml2solv.1
index e14b974..aeac7bd 100644
--- a/doc/repomdxml2solv.1
+++ b/doc/gen/repomdxml2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: repomdxml2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "REPOMDXML2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "REPOMDXML2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/rpmdb2solv.1 b/doc/gen/rpmdb2solv.1
index 2b4b931..79c6d26 100644
--- a/doc/rpmdb2solv.1
+++ b/doc/gen/rpmdb2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: rpmdb2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "RPMDB2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "RPMDB2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/rpmmd2solv.1 b/doc/gen/rpmmd2solv.1
index 2d8e245..44ea70f 100644
--- a/doc/rpmmd2solv.1
+++ b/doc/gen/rpmmd2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: rpmmd2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "RPMMD2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "RPMMD2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/rpms2solv.1 b/doc/gen/rpms2solv.1
index e67c6ef..11b3671 100644
--- a/doc/rpms2solv.1
+++ b/doc/gen/rpms2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: rpms2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "RPMS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "RPMS2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/susetags2solv.1 b/doc/gen/susetags2solv.1
index 9b07094..43a616a 100644
--- a/doc/susetags2solv.1
+++ b/doc/gen/susetags2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: susetags2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "SUSETAGS2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "SUSETAGS2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/testsolv.1 b/doc/gen/testsolv.1
index 0e71874..158aedc 100644
--- a/doc/testsolv.1
+++ b/doc/gen/testsolv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: testsolv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "TESTSOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "TESTSOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/updateinfoxml2solv.1 b/doc/gen/updateinfoxml2solv.1
index 20ab3ad..cd0386d 100644
--- a/doc/updateinfoxml2solv.1
+++ b/doc/gen/updateinfoxml2solv.1
@@ -1,13 +1,13 @@
'\" t
.\" Title: updateinfoxml2solv
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 08/26/2015
+.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
+.\" Date: 08/04/2017
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "UPDATEINFOXML2SOLV" "1" "08/26/2015" "libsolv" "LIBSOLV"
+.TH "UPDATEINFOXML2SOLV" "1" "08/04/2017" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/helix2solv.txt b/doc/helix2solv.txt
index f9b303f..40d523a 100644
--- a/doc/helix2solv.txt
+++ b/doc/helix2solv.txt
@@ -22,3 +22,7 @@ input and writes it in solv file format to standard output.
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/installcheck.txt b/doc/installcheck.txt
index 99eb279..5780772 100644
--- a/doc/installcheck.txt
+++ b/doc/installcheck.txt
@@ -27,3 +27,7 @@ file.
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/libsolv-bindings.txt b/doc/libsolv-bindings.txt
index 4de090f..83ae6c2 100644
--- a/doc/libsolv-bindings.txt
+++ b/doc/libsolv-bindings.txt
@@ -167,7 +167,7 @@ a foreach style:
libsolv's arrays are mapped to tcl's lists:
- TCL set jobs [list $job1 $job2]
+ TCL set jobs [list $job1 $job2]
TCL set problems [$solver solve $jobs]
TCL puts "We have [llength $problems] problems..."
@@ -1173,9 +1173,9 @@ Add the contents of the mageia/mandriva repository metadata (the
"synthesis.hdlist" file) to the repository.
bool add_mdk_info(FILE *fp, int flags = 0)
- $repo->add_mdk($fp);
- repo.add_mdk(fp)
- repo.add_mdk(fp)
+ $repo->add_mdk_info($fp);
+ repo.add_mdk_info(fp)
+ repo.add_mdk_info(fp)
Extend the packages from the synthesis file with the info.xml and files.xml
data. Do not forget to specify *REPO_EXTEND_SOLVABLES*.
@@ -1426,7 +1426,7 @@ Note that "equal" does not mean that the evr is identical.
solvable.matchesdep(keyname, dep)
solvable.matchesdep?(keyname, dep)
-Return true if the dependencies stored in keyname match the specified dependeny.
+Return true if the dependencies stored in keyname match the specified dependency.
Selection Selection(int setflags = 0)
my $sel = $solvable->Selection();
@@ -2136,7 +2136,7 @@ by setting this flag.
*SOLVER_FLAG_NEED_UPDATEPROVIDE*::
This is somewhat the opposite of SOLVER_FLAG_NO_UPDATEPROVIDE: Only
-packages that provied the installed package names are considered
+packages that provide the installed package names are considered
for updating.
*SOLVER_FLAG_SPLITPROVIDES*::
@@ -2464,6 +2464,23 @@ interfaces that show both the job result and the problems.
Return the reason why a specific solvable was installed or erased. For most of
the reasons the rule that triggered the decision is also returned.
+ Solvable *get_recommended(bool noselected=0);
+ my @solvables = $solver->get_recommended();
+ solvables = solver.get_recommended()
+ solvables = solver.get_recommended()
+
+Return all solvables that are recommended by the solver run result. This includes
+solvables included in the result, set noselected if you want to filter those.
+
+ Solvable *get_suggested(bool noselected=0);
+ my @solvables = $solver->get_suggested();
+ solvables = solver.get_suggested()
+ solvables = solver.get_suggested()
+
+Return all solvables that are suggested by the solver run result. This includes
+solvables included in the result, set noselected if you want to filter those.
+
+
The Problem Class
-----------------
Problems are the way of the solver to interact with the user. You can simply list
@@ -2500,8 +2517,8 @@ that somewhat describes the problem best to the user.
Rule *findallproblemrules(bool unfiltered = 0)
my @probrules = $problem->findallproblemrules();
- probrules = problem.findallproblemrule()
- probrules = problem.findallproblemrule()
+ probrules = problem.findallproblemrules()
+ probrules = problem.findallproblemrules()
Return all rules responsible for the problem. The returned set of rules contains
all the needed information why there was a problem, but it's hard to present
@@ -2790,7 +2807,7 @@ the solver class.
Create a job that implements the solution element. Add this job to the array
of jobs for all elements of type different to SOLVER_SOLUTION_JOB and
-SOLVER_SOLUTION_POOLJOB. For the later two, a SOLVER_NOOB Job is created,
+SOLVER_SOLUTION_POOLJOB. For the latter two, a SOLVER_NOOB Job is created,
you should replace the old job with the new one.
const char *str()
@@ -3364,9 +3381,10 @@ area.
data.extend_to_repo()
Extend the repodata so that it has the same size as the repo it belongs to.
-This method is only needed when switching to a just written repodata extension
-to make the repodata match the written extension (which is always of the
-size of the repo).
+This method is needed when setting up a new extension repodata so that it
+matches the repository size. It is also needed when switching to a just written
+repodata extension to make the repodata match the written extension (which is
+always of the size of the repo).
<equality>
if ($data1 == $data2)
@@ -3541,3 +3559,6 @@ Author
------
Michael Schroeder <mls@suse.de>
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/libsolv-constantids.txt b/doc/libsolv-constantids.txt
index e067642..907a7e5 100644
--- a/doc/libsolv-constantids.txt
+++ b/doc/libsolv-constantids.txt
@@ -678,3 +678,6 @@ Author
------
Michael Schroeder <mls@suse.de>
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/libsolv-history.txt b/doc/libsolv-history.txt
index da59fe5..d0a5e62 100644
--- a/doc/libsolv-history.txt
+++ b/doc/libsolv-history.txt
@@ -111,3 +111,7 @@ were removed in February.
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/libsolv-pool.txt b/doc/libsolv-pool.txt
index 69291a4..cc7707a 100644
--- a/doc/libsolv-pool.txt
+++ b/doc/libsolv-pool.txt
@@ -408,11 +408,33 @@ A conditional dependency, the ``name'' sub-dependency is only considered if
the ``evr'' sub-dependency is fulfilled. See the section about boolean
dependencies about more information.
+*REL_UNLESS*::
+A conditional dependency, the ``name'' sub-dependency is only considered if
+the ``evr'' sub-dependency is not fulfilled. See the section about boolean
+dependencies about more information.
+
*REL_COMPAT*::
A compat dependency used in Haiku to represent version ranges. The
``name'' part is the actual version, the ``evr'' part is the backwards
compatibility version.
+*REL_KIND*::
+A pseudo dependency that limits the solvables to a specific kind.
+The kind is expected to be a prefix of the solvable name, e.g.
+``patch:foo'' would be of kind ``patch''. ``REL_KIND'' is only
+supported in the selection functions.
+
+*REL_MULTIARCH*::
+A debian multiarch annotation. The most common value for the ``evr''
+part is ``any''.
+
+*REL_ELSE*::
+The else part of a ``REL_COND'' or ``REL_UNLESS'' dependency. See the
+section about boolean dependencies.
+
+*REL_ERROR*::
+An illegal dependency. This is useful to encode dependency parse errors.
+
=== Functions ===
Id pool_str2id(Pool *pool, const char *str, int create);
@@ -815,10 +837,9 @@ SOLVER_FLAG_ALLOW_VENDORCHANGE flag.
Boolean Dependencies
--------------------
Boolean Dependencies allow to build complex expressions from simple
-dependencies. While rpm does not support boolean expressions in
-dependencies and debian only allows an "OR" expression, libsolv
-allows arbitrary complex expressions. The following basic types
-are supported:
+dependencies. Note that depending on the package manager only a subset
+of those may be useful. For example, debian currently only allows
+an "OR" expression.
*REL_OR*::
The expression is true if either the first dependency or the second
@@ -829,21 +850,33 @@ installed.
*REL_AND*::
The expression is true if both dependencies are true. The packages
fulfilling the dependencies may be different, i.e.
-``Supplements: perl AND python'' is true if both a package providing
-perl and a package providing python are installed. The solver currently
-only supports REL_AND in Supplements/Enhances dependencies, in other
-types of dependencies it gets treated as REL_WITH.
+``Supplements: perl REL_AND python'' is true if both a package providing
+perl and a package providing python are installed.
*REL_WITH*::
The expression is true if both dependencies are true and are fulfilled by
-the same package. Thus ``Supplements: perl AND python'' would only be true
+the same package. Thus ``Supplements: perl REL_WITH python'' would only be true
if a package is installed that provides both dependencies (some kind
of multi-language interpreter).
*REL_COND*::
The expression is true if the first dependency is true or the second
-dependency is false. Libsolv currently does not support this type of
-dependency in the solver code.
+dependency is false. ``A REL_COND B'' is equivalent to
+``A REL_OR (NOT B)'' (except that libsolv does not expose ``NOT'').
+
+*REL_UNLESS*::
+The expression is true if the first dependency is true and the second
+dependency is false. ``A REL_UNLESS B'' is equivalent to
+``A REL_AND (NOT B)'' (except that libsolv does not expose ``NOT'').
+
+*REL_ELSE*::
+The ``else'' part of a ``REL_COND'' or ``REL_UNLESS'' dependency.
+It has to be directly in the evr part of the condition,
+e.g. ``foo REL_COND (bar REL_ELSE baz)''.
+For ``REL_COND'' this is equivalent to writing
+``(foo REL_COND bar) REL_AND (bar REL_OR baz)''.
+For ``REL_UNLESS'' this is equivalent to writing
+``(foo REL_UNLESS bar) REL_OR (bar REL_AND baz)''.
Each sub-dependency of a boolean dependency can in turn be a boolean
dependency, so you can chain them to create complex dependencies.
@@ -882,3 +915,6 @@ Author
------
Michael Schroeder <mls@suse.de>
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/libsolv.txt b/doc/libsolv.txt
index af44168..f101808 100644
--- a/doc/libsolv.txt
+++ b/doc/libsolv.txt
@@ -56,3 +56,6 @@ Author
------
Michael Schroeder <mls@suse.de>
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/mdk2solv.txt b/doc/mdk2solv.txt
index 2616a87..eb2ac14 100644
--- a/doc/mdk2solv.txt
+++ b/doc/mdk2solv.txt
@@ -31,3 +31,7 @@ genhdlist2(1)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/mergesolv.txt b/doc/mergesolv.txt
index bbe8c72..8ae67d1 100644
--- a/doc/mergesolv.txt
+++ b/doc/mergesolv.txt
@@ -23,3 +23,7 @@ Autoexpand SUSE pattern and product provides into packages.
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/repomdxml2solv.txt b/doc/repomdxml2solv.txt
index feb859c..3b77820 100644
--- a/doc/repomdxml2solv.txt
+++ b/doc/repomdxml2solv.txt
@@ -34,3 +34,7 @@ rpmmd2solv(1), mergesolv(1), createrepo(8)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/rpmdb2solv.txt b/doc/rpmdb2solv.txt
index 0c4585f..ad8314f 100644
--- a/doc/rpmdb2solv.txt
+++ b/doc/rpmdb2solv.txt
@@ -57,3 +57,7 @@ rpms2solv(1)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/rpmmd2solv.txt b/doc/rpmmd2solv.txt
index c72ccc9..f103f06 100644
--- a/doc/rpmmd2solv.txt
+++ b/doc/rpmmd2solv.txt
@@ -28,3 +28,7 @@ repomdxml2solv(1), mergesolv(1), createrepo(8)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/rpms2solv.txt b/doc/rpms2solv.txt
index 244dffb..11bdcf0 100644
--- a/doc/rpms2solv.txt
+++ b/doc/rpms2solv.txt
@@ -46,3 +46,7 @@ rpmdb2solv(1)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/susetags2solv.txt b/doc/susetags2solv.txt
index 9a2e2f1..0d61c4d 100644
--- a/doc/susetags2solv.txt
+++ b/doc/susetags2solv.txt
@@ -37,3 +37,7 @@ Autoexpand SUSE pattern and product provides into packages.
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/testsolv.txt b/doc/testsolv.txt
index dc3a34e..eb52d95 100644
--- a/doc/testsolv.txt
+++ b/doc/testsolv.txt
@@ -39,3 +39,7 @@ to encountered problems.
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/doc/updateinfoxml2solv.txt b/doc/updateinfoxml2solv.txt
index 7e7c5fc..6ebdeb4 100644
--- a/doc/updateinfoxml2solv.txt
+++ b/doc/updateinfoxml2solv.txt
@@ -25,3 +25,7 @@ mergesolv(1), createrepo(8)
Author
------
Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
diff --git a/examples/solv/deltarpm.c b/examples/solv/deltarpm.c
index 551d570..438c2d8 100644
--- a/examples/solv/deltarpm.c
+++ b/examples/solv/deltarpm.c
@@ -75,7 +75,7 @@ trydeltadownload(Solvable *s, const char *loc)
seq = pool_tmpappend(pool, seq, "-", pool_lookup_str(pool, SOLVID_POS, DELTA_SEQ_NUM));
if (strchr(seq, '\'') != 0)
continue;
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
sprintf(cmd, "/usr/bin/applydeltarpm -a '%s' -c -s '", archstr);
#else
sprintf(cmd, "/usr/bin/applydeltarpm -c -s '");
@@ -101,7 +101,7 @@ trydeltadownload(Solvable *s, const char *loc)
continue;
/* got it, now reconstruct */
newfd = opentmpfile();
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
sprintf(cmd, "applydeltarpm -a '%s' /dev/fd/%d /dev/fd/%d", archstr, fileno(fp), newfd);
#else
sprintf(cmd, "applydeltarpm /dev/fd/%d /dev/fd/%d", fileno(fp), newfd);
diff --git a/examples/solv/repoinfo.c b/examples/solv/repoinfo.c
index 91f7c28..6273972 100644
--- a/examples/solv/repoinfo.c
+++ b/examples/solv/repoinfo.c
@@ -18,13 +18,13 @@
#include "repoinfo.h"
#include "repoinfo_cache.h"
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
#include "repoinfo_config_yum.h"
#endif
#if defined(DEBIAN)
#include "repoinfo_config_debian.h"
#endif
-#if defined(MANDRIVA) || defined(MAGEIA)
+#if defined(MANDRIVA)
#include "repoinfo_config_urpmi.h"
#endif
@@ -80,7 +80,7 @@ free_repoinfos(struct repoinfo *repoinfos, int nrepoinfos)
solv_free(cinfo->components);
}
solv_free(repoinfos);
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
yum_substitute((Pool *)0, 0); /* free data */
#endif
}
@@ -89,10 +89,10 @@ struct repoinfo *
read_repoinfos(Pool *pool, int *nrepoinfosp)
{
struct repoinfo *repoinfos = 0;
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
repoinfos = read_repoinfos_yum(pool, nrepoinfosp);
#endif
-#if defined(MANDRIVA) || defined(MAGEIA)
+#if defined(MANDRIVA)
repoinfos = read_repoinfos_urpmi(pool, nrepoinfosp);
#endif
#if defined(DEBIAN)
diff --git a/examples/solv/repoinfo_config_yum.c b/examples/solv/repoinfo_config_yum.c
index 6e2e66a..efccf1e 100644
--- a/examples/solv/repoinfo_config_yum.c
+++ b/examples/solv/repoinfo_config_yum.c
@@ -1,4 +1,4 @@
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
#include <stdio.h>
#include <stdlib.h>
@@ -14,7 +14,7 @@
#include "repoinfo_config_yum.h"
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
# define REPOINFO_PATH "/etc/yum.repos.d"
#endif
#ifdef SUSE
@@ -48,7 +48,7 @@ yum_substitute(Pool *pool, char *line)
queue_init(&q);
rpmstate = rpm_state_create(pool, pool_get_rootdir(pool));
- rpm_installedrpmdbids(rpmstate, "Providename", "redhat-release", &q);
+ rpm_installedrpmdbids(rpmstate, "Providename", "system-release", &q);
if (q.count)
{
void *handle;
@@ -62,7 +62,7 @@ yum_substitute(Pool *pool, char *line)
queue_free(&q);
if (!releaseevr)
{
- fprintf(stderr, "no installed package provides 'redhat-release', cannot determine $releasever\n");
+ fprintf(stderr, "no installed package provides 'system-release', cannot determine $releasever\n");
exit(1);
}
}
@@ -160,7 +160,7 @@ read_repoinfos_yum(Pool *pool, int *nrepoinfosp)
cinfo->type = TYPE_RPMMD;
cinfo->autorefresh = 1;
cinfo->priority = 99;
-#ifndef FEDORA
+#if !defined(FEDORA) && !defined(MAGEIA)
cinfo->repo_gpgcheck = 1;
#endif
cinfo->metadata_expire = METADATA_EXPIRE;
diff --git a/examples/solv/repoinfo_download.c b/examples/solv/repoinfo_download.c
index 5ba3014..f5ba8b9 100644
--- a/examples/solv/repoinfo_download.c
+++ b/examples/solv/repoinfo_download.c
@@ -13,6 +13,9 @@
#include "repoinfo.h"
#include "mirror.h"
#include "checksig.h"
+#if defined(FEDORA) || defined(MAGEIA)
+#include "repoinfo_config_yum.h"
+#endif
#include "repoinfo_download.h"
static inline int
@@ -89,7 +92,7 @@ curlfopen(struct repoinfo *cinfo, const char *file, int uncompress, const unsign
fclose(fp);
if (!cinfo->baseurl)
return 0;
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
if (strchr(cinfo->baseurl, '$'))
{
char *b = yum_substitute(cinfo->repo->pool, cinfo->baseurl);
diff --git a/examples/solv/solv.c b/examples/solv/solv.c
index 3301126..615c83d 100644
--- a/examples/solv/solv.c
+++ b/examples/solv/solv.c
@@ -49,7 +49,7 @@
#include "fileconflicts.h"
#include "deltarpm.h"
#endif
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
#include "patchjobs.h"
#endif
@@ -195,7 +195,7 @@ usage(int r)
fprintf(stderr, " search: search name/summary/description\n");
fprintf(stderr, " update: update installed packages\n");
fprintf(stderr, " verify: check dependencies of installed packages\n");
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
fprintf(stderr, " patch: install newest maintenance updates\n");
#endif
fprintf(stderr, "\n");
@@ -244,7 +244,7 @@ main(int argc, char **argv)
mainmode = MODE_INSTALL;
mode = SOLVER_INSTALL;
}
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
else if (!strcmp(argv[0], "patch"))
{
mainmode = MODE_PATCH;
@@ -638,7 +638,7 @@ main(int argc, char **argv)
exit(0);
}
-#if defined(SUSE) || defined(FEDORA)
+#if defined(SUSE) || defined(FEDORA) || defined(MAGEIA)
if (mainmode == MODE_PATCH)
add_patchjobs(pool, &job);
#endif
@@ -667,7 +667,7 @@ main(int argc, char **argv)
rerunsolver:
solv = solver_create(pool);
solver_set_flag(solv, SOLVER_FLAG_SPLITPROVIDES, 1);
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
solver_set_flag(solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, 1);
#endif
if (mainmode == MODE_ERASE)
diff --git a/ext/pool_parserpmrichdep.c b/ext/pool_parserpmrichdep.c
index d3e559e..93d77f8 100644
--- a/ext/pool_parserpmrichdep.c
+++ b/ext/pool_parserpmrichdep.c
@@ -17,10 +17,13 @@ static struct RichOpComp {
int l;
Id fl;
} RichOps[] = {
- { "and", 3, REL_AND },
- { "or", 2, REL_OR },
- { "if", 2, REL_COND },
- { "else", 4, REL_ELSE },
+ { "and", 3, REL_AND },
+ { "or", 2, REL_OR },
+ { "if", 2, REL_COND },
+ { "unless", 6, REL_UNLESS },
+ { "else", 4, REL_ELSE },
+ { "with", 4, REL_WITH },
+ { "without", 7, REL_WITHOUT },
{ NULL, 0, 0},
};
@@ -106,7 +109,7 @@ parseRichDep(Pool *pool, const char **depp, Id chainfl)
fl = op->fl;
if (!fl)
return 0;
- if (chainfl == REL_COND && fl == REL_ELSE)
+ if ((chainfl == REL_COND || chainfl == REL_UNLESS) && fl == REL_ELSE)
chainfl = 0;
if (chainfl && fl != chainfl)
return 0;
diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c
index b98720a..9fb5a29 100644
--- a/ext/repo_rpmdb.c
+++ b/ext/repo_rpmdb.c
@@ -177,7 +177,6 @@ typedef struct rpmhead {
int cnt;
unsigned int dcnt;
unsigned char *dp;
- int forcebinary; /* sigh, see rh#478907 */
unsigned char data[1];
} RpmHead;
@@ -366,6 +365,18 @@ headbinary(RpmHead *h, int tag, unsigned int *sizep)
return h->dp + o;
}
+static int
+headissourceheuristic(RpmHead *h)
+{
+ unsigned int i, o;
+ unsigned char *d = headfindtag(h, TAG_DIRNAMES);
+ if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8)
+ return 0;
+ o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
+ i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
+ return i == 1 && o < h->dcnt && !h->dp[o] ? 1 : 0;
+}
+
static char *headtoevr(RpmHead *h)
{
unsigned int epoch;
@@ -989,7 +1000,7 @@ rpmhead2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhe
return 0;
s->name = pool_str2id(pool, name, 1);
sourcerpm = headstring(rpmhead, TAG_SOURCERPM);
- if (sourcerpm || (rpmhead->forcebinary && !headexists(rpmhead, TAG_SOURCEPACKAGE)))
+ if (sourcerpm || !(headexists(rpmhead, TAG_SOURCEPACKAGE) || headissourceheuristic(rpmhead)))
s->arch = pool_str2id(pool, headstring(rpmhead, TAG_ARCH), 1);
else
{
@@ -1175,7 +1186,7 @@ rpmdbid2db(unsigned char *db, Id id, int byteswapped)
#endif
}
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
int
serialize_dbenv_ops(struct rpmdbstate *state)
{
@@ -1216,7 +1227,7 @@ opendbenv(struct rpmdbstate *state)
if (db_env_create(&dbenv, 0))
return pool_error(state->pool, 0, "db_env_create: %s", strerror(errno));
-#if defined(FEDORA) && (DB_VERSION_MAJOR >= 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5))
+#if (defined(FEDORA) || defined(MAGEIA)) && (DB_VERSION_MAJOR >= 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5))
dbenv->set_thread_count(dbenv, 8);
#endif
snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm", rootdir ? rootdir : "");
@@ -1230,7 +1241,7 @@ opendbenv(struct rpmdbstate *state)
}
else
{
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
int serialize_fd = serialize_dbenv_ops(state);
r = dbenv->open(dbenv, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0644);
if (serialize_fd >= 0)
@@ -1252,13 +1263,13 @@ opendbenv(struct rpmdbstate *state)
static void
closedbenv(struct rpmdbstate *state)
{
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
uint32_t eflags = 0;
#endif
if (!state->dbenv)
return;
-#ifdef FEDORA
+#if defined(FEDORA) || defined(MAGEIA)
(void)state->dbenv->get_open_flags(state->dbenv, &eflags);
if (!(eflags & DB_PRIVATE))
{
@@ -1466,7 +1477,6 @@ getrpm_dbdata(struct rpmdbstate *state, DBT *dbdata, int dbid)
state->rpmhead = solv_realloc(state->rpmhead, sizeof(*rpmhead) + state->rpmheadsize);
}
rpmhead = state->rpmhead;
- rpmhead->forcebinary = 1;
rpmhead->cnt = cnt;
rpmhead->dcnt = dsize;
memcpy(rpmhead->data, (unsigned char *)dbdata->data + 8, l);
@@ -2137,7 +2147,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
Id chksumtype = 0;
Chksum *chksumh = 0;
Chksum *leadsigchksumh = 0;
- int forcebinary = 0;
data = repo_add_repodata(repo, flags);
@@ -2167,7 +2176,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
fclose(fp);
return 0;
}
- forcebinary = lead[6] != 0 || lead[7] != 1;
if (chksumh)
solv_chksum_add(chksumh, lead, 96 + 16);
if (leadsigchksumh)
@@ -2215,7 +2223,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
solv_chksum_add(chksumh, rpmhead->data, sigdsize);
if (leadsigchksumh)
solv_chksum_add(leadsigchksumh, rpmhead->data, sigdsize);
- rpmhead->forcebinary = 0;
rpmhead->cnt = sigcnt;
rpmhead->dcnt = sigdsize - sigcnt * 16;
rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
@@ -2307,7 +2314,6 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
rpmhead->data[l] = 0;
if (chksumh)
solv_chksum_add(chksumh, rpmhead->data, l);
- rpmhead->forcebinary = forcebinary;
rpmhead->cnt = sigcnt;
rpmhead->dcnt = sigdsize;
rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
@@ -2588,7 +2594,7 @@ rpm_query(void *rpmhandle, Id what)
if (!name)
name = "";
sourcerpm = headstring(rpmhead, TAG_SOURCERPM);
- if (sourcerpm || (rpmhead->forcebinary && !headexists(rpmhead, TAG_SOURCEPACKAGE)))
+ if (sourcerpm || !(headexists(rpmhead, TAG_SOURCEPACKAGE) || headissourceheuristic(rpmhead)))
arch = headstring(rpmhead, TAG_ARCH);
else
{
@@ -2680,14 +2686,12 @@ rpm_byfp(void *rpmstate, FILE *fp, const char *name)
RpmHead *rpmhead;
unsigned int sigdsize, sigcnt, l;
unsigned char lead[4096];
- int forcebinary = 0;
if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb)
{
pool_error(state->pool, 0, "%s: not a rpm", name);
return 0;
}
- forcebinary = lead[6] != 0 || lead[7] != 1;
if (lead[78] != 0 || lead[79] != 5)
{
pool_error(state->pool, 0, "%s: not a V5 header", name);
@@ -2749,7 +2753,6 @@ rpm_byfp(void *rpmstate, FILE *fp, const char *name)
return 0;
}
rpmhead->data[l] = 0;
- rpmhead->forcebinary = forcebinary;
rpmhead->cnt = sigcnt;
rpmhead->dcnt = sigdsize;
rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
@@ -2787,7 +2790,6 @@ rpm_byrpmh(void *rpmstate, Header h)
memcpy(rpmhead->data, uh + 8, l);
rpmhead->data[l] = 0;
free((void *)uh);
- rpmhead->forcebinary = 0;
rpmhead->cnt = sigcnt;
rpmhead->dcnt = sigdsize;
rpmhead->dp = rpmhead->data + sigcnt * 16;
diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c
index 41c7a78..52d5e5e 100644
--- a/ext/repo_susetags.c
+++ b/ext/repo_susetags.c
@@ -345,6 +345,77 @@ toevr(Pool *pool, struct parsedata *pd, const char *version, const char *release
}
+static inline void record_share(struct parsedata *pd, Id handle, Id name, Id evr, Id arch)
+{
+ Repo *repo = pd->repo;
+ int i = handle - repo->start;
+ if (i >= pd->nshare)
+ {
+ pd->share_with = solv_realloc2(pd->share_with, i + 256, sizeof(*pd->share_with));
+ memset(pd->share_with + pd->nshare, 0, (i + 256 - pd->nshare) * sizeof(*pd->share_with));
+ pd->nshare = i + 256;
+ }
+ pd->share_with[i].name = name;
+ pd->share_with[i].evr = evr;
+ pd->share_with[i].arch = arch;
+}
+
+static void process_shares(struct parsedata *pd)
+{
+ Pool *pool = pd->pool;
+ Repo *repo = pd->repo;
+ Repodata *data = pd->data;
+ int i, last_found;
+ Map keyidmap;
+
+ map_init(&keyidmap, data->nkeys);
+ for (i = 1; i < data->nkeys; i++)
+ {
+ Id keyname = data->keys[i].name;
+ if (keyname == SOLVABLE_INSTALLSIZE || keyname == SOLVABLE_DISKUSAGE || keyname == SOLVABLE_FILELIST)
+ continue;
+ if (keyname == SOLVABLE_MEDIADIR || keyname == SOLVABLE_MEDIAFILE || keyname == SOLVABLE_MEDIANR)
+ continue;
+ if (keyname == SOLVABLE_DOWNLOADSIZE || keyname == SOLVABLE_CHECKSUM)
+ continue;
+ if (keyname == SOLVABLE_SOURCENAME || keyname == SOLVABLE_SOURCEARCH || keyname == SOLVABLE_SOURCEEVR)
+ continue;
+ if (keyname == SOLVABLE_PKGID || keyname == SOLVABLE_HDRID || keyname == SOLVABLE_LEADSIGID)
+ continue;
+ if (keyname == SUSETAGS_SHARE_NAME || keyname == SUSETAGS_SHARE_EVR || keyname == SUSETAGS_SHARE_ARCH)
+ continue;
+ MAPSET(&keyidmap, i);
+ }
+ last_found = 0;
+ for (i = 0; i < pd->nshare; i++)
+ {
+ unsigned int n, nn;
+ Solvable *found = 0;
+ if (!pd->share_with[i].name)
+ continue;
+ for (n = repo->start, nn = repo->start + last_found; n < repo->end; n++, nn++)
+ {
+ if (nn >= repo->end)
+ nn = repo->start;
+ found = pool->solvables + nn;
+ if (found->repo == repo
+ && found->name == pd->share_with[i].name
+ && found->evr == pd->share_with[i].evr
+ && found->arch == pd->share_with[i].arch)
+ {
+ last_found = nn - repo->start;
+ break;
+ }
+ }
+ if (n != repo->end)
+ repodata_merge_some_attrs(data, repo->start + i, repo->start + last_found, &keyidmap, 0);
+ }
+ pd->share_with = solv_free(pd->share_with);
+ pd->nshare = 0;
+ map_free(&keyidmap);
+}
+
+
/*
* parse susetags
*
@@ -365,7 +436,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
int intag = 0;
int intag_linestart = 0;
int cummulate = 0;
- int indesc = 0;
+ int notfound = 0;
int indelta = 0;
int last_found_pack = 0;
Id first_new_pkg = 0;
@@ -380,7 +451,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
if ((flags & (SUSETAGS_EXTEND|REPO_EXTEND_SOLVABLES)) != 0 && repo->nrepodata)
{
joinhash = joinhash_init(repo, &joinhashm);
- indesc = 1;
}
data = repo_add_repodata(repo, flags);
@@ -423,15 +493,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
arch = lookup_shared_id(sdata, p, SUSETAGS_SHARE_ARCH, pool->solvables[p].arch, sdata == data);
if (!arch)
continue;
- if (p - repo->start >= pd.nshare)
- {
- pd.share_with = solv_realloc2(pd.share_with, p - repo->start + 256, sizeof(*pd.share_with));
- memset(pd.share_with + pd.nshare, 0, (p - repo->start + 256 - pd.nshare) * sizeof(*pd.share_with));
- pd.nshare = p - repo->start + 256;
- }
- pd.share_with[p - repo->start].name = name;
- pd.share_with[p - repo->start].evr = evr;
- pd.share_with[p - repo->start].arch = arch;
+ record_share(&pd, p, name, evr, arch);
}
}
}
@@ -558,128 +620,87 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
tag = tag_from_string(line);
- if (indelta)
- {
- /* Example:
- =Dlt: subversion 1.6.16 1.3.1 i586
- =Dsq: subversion 1.6.15 4.2 i586 d57b3fc86e7a2f73796e8e35b96fa86212c910
- =Cks: SHA1 14a8410cf741856a5d70d89dab62984dba6a1ca7
- =Loc: 1 subversion-1.6.15_1.6.16-4.2_1.3.1.i586.delta.rpm
- =Siz: 81558
- */
- switch (tag)
- {
- case CTAG('=', 'D', 's', 'q'):
- {
- Id evr;
- if (split(line + 5, sp, 5) != 5)
- continue;
- repodata_set_id(data, handle, DELTA_SEQ_NAME, pool_str2id(pool, sp[0], 1));
- evr = toevr(pool, &pd, sp[1], sp[2]);
- repodata_set_id(data, handle, DELTA_SEQ_EVR, evr);
- /* repodata_set_id(data, handle, DELTA_SEQ_ARCH, pool_str2id(pool, sp[3], 1)); */
- repodata_set_str(data, handle, DELTA_SEQ_NUM, sp[4]);
- repodata_set_id(data, handle, DELTA_BASE_EVR, evr);
- continue;
- }
- case CTAG('=', 'C', 'k', 's'):
- set_checksum(&pd, data, handle, DELTA_CHECKSUM, line + 6);
- continue;
- case CTAG('=', 'L', 'o', 'c'):
- {
- int i = split(line + 6, sp, 3);
- if (i != 2 && i != 3)
- {
- pd.ret = pool_error(pool, -1, "susetags: line %d: bad location line '%s'\n", pd.lineno, line);
- continue;
- }
- repodata_set_deltalocation(data, handle, atoi(sp[0]), i == 3 ? sp[2] : 0, sp[1]);
- continue;
- }
- case CTAG('=', 'S', 'i', 'z'):
- if (split(line + 6, sp, 3) == 2)
- repodata_set_num(data, handle, DELTA_DOWNLOADSIZE, strtoull(sp[0], 0, 10));
- continue;
- case CTAG('=', 'P', 'k', 'g'):
- case CTAG('=', 'P', 'a', 't'):
- case CTAG('=', 'D', 'l', 't'):
- handle = 0;
- indelta = 0;
- break;
- default:
- pool_debug(pool, SOLV_ERROR, "susetags: unknown line: %d: %s\n", pd.lineno, line);
- continue;
- }
- }
-
- /*
- * start of (next) package or pattern or delta
- *
- * =Pkg: <name> <version> <release> <architecture>
- * (=Pat: ...)
- */
- if (tag == CTAG('=', 'D', 'l', 't'))
- {
+ /* handle global tags and tags that start a new section */
+ switch (tag)
+ {
+ case CTAG('=', 'V', 'e', 'r'):
+ /* start of a new file */
if (s)
finish_solvable(&pd, s, freshens);
s = 0;
- pd.kind = 0;
- if (split(line + 5, sp, 5) != 4)
+ handle = 0;
+ freshens = 0;
+ indelta = 0;
+ notfound = 0;
+ last_found_pack = 0;
+ if (createdpkgs)
{
- pd.ret = pool_error(pool, -1, "susetags: line %d: bad line '%s'\n", pd.lineno, line);
- break;
+ solv_free(joinhash);
+ joinhash = joinhash_init(repo, &joinhashm);
+ createdpkgs = 0;
}
- handle = repodata_new_handle(data);
- repodata_set_id(data, handle, DELTA_PACKAGE_NAME, pool_str2id(pool, sp[0], 1));
- repodata_set_id(data, handle, DELTA_PACKAGE_EVR, toevr(pool, &pd, sp[1], sp[2]));
- repodata_set_id(data, handle, DELTA_PACKAGE_ARCH, pool_str2id(pool, sp[3], 1));
- repodata_add_flexarray(data, SOLVID_META, REPOSITORY_DELTAINFO, handle);
- indelta = 1;
continue;
- }
- if (tag == CTAG('=', 'P', 'k', 'g')
- || tag == CTAG('=', 'P', 'a', 't'))
- {
- /* If we have an old solvable, complete it by filling in some
- default stuff. */
+
+ case CTAG('=', 'L', 'a', 'n'):
+ /* define language of the following material */
+ pd.language = solv_free(pd.language);
+ memset(pd.langcache, 0, sizeof(pd.langcache));
+ if (line[6])
+ pd.language = solv_strdup(line + 6);
+ continue;
+
+ case CTAG('=', 'P', 'k', 'g'): /* start of a package */
+ case CTAG('=', 'P', 'a', 't'): /* start of a pattern */
+ case CTAG('=', 'D', 'l', 't'): /* start of a delta */
+ /* =Pkg: <name> <version> <release> <architecture> */
+ /* If we have an old solvable, complete it by filling in some default stuff. */
if (s)
finish_solvable(&pd, s, freshens);
+ s = 0;
+ handle = 0;
+ freshens = 0;
+ indelta = 0;
+ notfound = 0;
- /*
- * define kind
- */
-
+ /* define kind */
pd.kind = 0;
- if (line[3] == 't')
+ if (tag == CTAG('=', 'P', 'a', 't'))
pd.kind = "pattern";
- /*
- * parse nevra
- */
-
+ /* parse nevra */
if (split(line + 5, sp, 5) != 4)
{
pd.ret = pool_error(pool, -1, "susetags: line %d: bad line '%s'\n", pd.lineno, line);
break;
}
- s = 0;
- freshens = 0;
+
+ if (tag == CTAG('=', 'D', 'l', 't'))
+ {
+ /* start new delta */
+ handle = repodata_new_handle(data);
+ repodata_set_id(data, handle, DELTA_PACKAGE_NAME, pool_str2id(pool, sp[0], 1));
+ repodata_set_id(data, handle, DELTA_PACKAGE_EVR, toevr(pool, &pd, sp[1], sp[2]));
+ repodata_set_id(data, handle, DELTA_PACKAGE_ARCH, pool_str2id(pool, sp[3], 1));
+ repodata_add_flexarray(data, SOLVID_META, REPOSITORY_DELTAINFO, handle);
+ indelta = 1;
+ continue;
+ }
if (joinhash)
{
/* data join operation. find solvable matching name/arch/evr and
* add data to it */
- Id name, evr, arch;
+ Id name, arch;
/* we don't use the create flag here as a simple pre-check for existance */
if (pd.kind)
name = pool_str2id(pool, join2(&pd.jd, pd.kind, ":", sp[0]), 0);
else
name = pool_str2id(pool, sp[0], 0);
- evr = toevr(pool, &pd, sp[1], sp[2]);
arch = pool_str2id(pool, sp[3], 0);
if (name && arch)
{
Id start = (flags & REPO_EXTEND_SOLVABLES) ? 0 : first_new_pkg;
+ Id evr = toevr(pool, &pd, sp[1], sp[2]);
if (repo->start + last_found_pack + 1 >= start && repo->start + last_found_pack + 1 < repo->end)
{
s = pool->solvables + repo->start + last_found_pack + 1;
@@ -691,7 +712,10 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
}
/* do not create new packages in EXTEND_SOLVABLES mode */
if (!s && (flags & REPO_EXTEND_SOLVABLES) != 0)
- continue;
+ {
+ notfound = 1;
+ continue;
+ }
/* fallthrough to package creation */
}
if (!s)
@@ -709,21 +733,74 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
first_new_pkg = s - pool->solvables;
createdpkgs = 1;
}
+ handle = s - pool->solvables;
last_found_pack = (s - pool->solvables) - repo->start;
- if (data)
- handle = s - pool->solvables;
+ continue;
+
+ default:
+ break;
}
- /* If we have no current solvable to add to, ignore all further lines
- for it. Probably invalid input data in the second set of
- solvables. */
- if (indesc >= 2 && !s)
- {
+ /* handle delta tags */
+ if (indelta)
+ {
+ /* Example:
+ =Dlt: subversion 1.6.16 1.3.1 i586
+ =Dsq: subversion 1.6.15 4.2 i586 d57b3fc86e7a2f73796e8e35b96fa86212c910
+ =Cks: SHA1 14a8410cf741856a5d70d89dab62984dba6a1ca7
+ =Loc: 1 subversion-1.6.15_1.6.16-4.2_1.3.1.i586.delta.rpm
+ =Siz: 81558
+ */
+ switch (tag)
+ {
+ case CTAG('=', 'D', 's', 'q'):
+ {
+ Id evr;
+ if (split(line + 5, sp, 5) != 5)
+ continue;
+ repodata_set_id(data, handle, DELTA_SEQ_NAME, pool_str2id(pool, sp[0], 1));
+ evr = toevr(pool, &pd, sp[1], sp[2]);
+ repodata_set_id(data, handle, DELTA_SEQ_EVR, evr);
+ /* repodata_set_id(data, handle, DELTA_SEQ_ARCH, pool_str2id(pool, sp[3], 1)); */
+ repodata_set_str(data, handle, DELTA_SEQ_NUM, sp[4]);
+ repodata_set_id(data, handle, DELTA_BASE_EVR, evr);
+ continue;
+ }
+ case CTAG('=', 'C', 'k', 's'):
+ set_checksum(&pd, data, handle, DELTA_CHECKSUM, line + 6);
+ continue;
+ case CTAG('=', 'L', 'o', 'c'):
+ {
+ int i = split(line + 6, sp, 3);
+ if (i != 2 && i != 3)
+ {
+ pd.ret = pool_error(pool, -1, "susetags: line %d: bad location line '%s'\n", pd.lineno, line);
+ continue;
+ }
+ repodata_set_deltalocation(data, handle, atoi(sp[0]), i == 3 ? sp[2] : 0, sp[1]);
+ continue;
+ }
+ case CTAG('=', 'S', 'i', 'z'):
+ if (split(line + 6, sp, 3) == 2)
+ repodata_set_num(data, handle, DELTA_DOWNLOADSIZE, strtoull(sp[0], 0, 10));
+ continue;
+ default:
+ pool_debug(pool, SOLV_WARN, "susetags: unknown line: %d: %s\n", pd.lineno, line);
+ continue;
+ }
+ }
+
+ /* we need a solvable for all other tags */
+ if (!s)
+ {
+ if (notfound)
+ continue; /* did not find the solvable to extend */
#if 0
- pool_debug(pool, SOLV_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
+ pool_debug(pool, SOLV_WARN, "susetags: stray line: %d: %s\n", pd.lineno, line);
#endif
continue;
}
+
switch (tag)
{
case CTAG('=', 'P', 'r', 'v'): /* provides */
@@ -754,11 +831,9 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
continue;
case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */
if (pd.kind)
- {
- s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */
- }
+ s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* pattern: package requires */
else
- s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
+ s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* pre-requires */
continue;
case CTAG('=', 'O', 'b', 's'): /* obsoletes */
s->obsoletes = adddep(pool, &pd, s->obsoletes, line, 0, pd.kind);
@@ -802,17 +877,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
case CTAG('=', 'P', 'e', 'n'): /* pattern: package enhances */
s->enhances = adddep(pool, &pd, s->enhances, line, 0, 0);
continue;
- case CTAG('=', 'V', 'e', 'r'): /* - version - */
- last_found_pack = 0;
- handle = 0;
- indesc++;
- if (createdpkgs)
- {
- solv_free(joinhash);
- joinhash = joinhash_init(repo, &joinhashm);
- createdpkgs = 0;
- }
- continue;
case CTAG('=', 'V', 'n', 'd'): /* vendor */
s->vendor = pool_str2id(pool, line + 6, 1);
continue;
@@ -880,8 +944,8 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
k = atoi(line + 6);
if (k || !strcasecmp(line + 6, "true"))
repodata_set_void(data, handle, SOLVABLE_ISVISIBLE);
+ continue;
}
- continue;
case CTAG('=', 'S', 'h', 'r'):
{
Id name, evr, arch;
@@ -893,15 +957,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
name = pool_str2id(pool, sp[0], 1);
evr = toevr(pool, &pd, sp[1], sp[2]);
arch = pool_str2id(pool, sp[3], 1);
- if (last_found_pack >= pd.nshare)
- {
- pd.share_with = solv_realloc2(pd.share_with, last_found_pack + 256, sizeof(*pd.share_with));
- memset(pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof(*pd.share_with));
- pd.nshare = last_found_pack + 256;
- }
- pd.share_with[last_found_pack].name = name;
- pd.share_with[last_found_pack].evr = evr;
- pd.share_with[last_found_pack].arch = arch;
+ record_share(&pd, handle, name, evr, arch);
if ((flags & SUSETAGS_RECORD_SHARES) != 0)
{
if (s->name == name)
@@ -956,12 +1012,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
case CTAG('=', 'C', 'k', 's'):
set_checksum(&pd, data, handle, SOLVABLE_CHECKSUM, line + 6);
break;
- case CTAG('=', 'L', 'a', 'n'):
- pd.language = solv_free(pd.language);
- memset(pd.langcache, 0, sizeof(pd.langcache));
- if (line[6])
- pd.language = solv_strdup(line + 6);
- break;
case CTAG('=', 'F', 'l', 's'):
{
@@ -994,76 +1044,21 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
}
break;
- case CTAG('=', 'P', 'a', 't'):
- case CTAG('=', 'P', 'k', 'g'):
- break;
-
default:
#if 0
pool_debug(pool, SOLV_WARN, "susetags: unknown line: %d: %s\n", pd.lineno, line);
#endif
break;
}
-
}
if (s)
finish_solvable(&pd, s, freshens);
solv_free(pd.filelist);
- /* Shared attributes
- * (e.g. multiple binaries built from same source)
- */
+ /* process shared attributes (e.g. multiple binaries built from same source) */
if (pd.nshare)
- {
- int i, last_found;
- Map keyidmap;
-
- map_init(&keyidmap, data->nkeys);
- for (i = 1; i < data->nkeys; i++)
- {
- Id keyname = data->keys[i].name;
- if (keyname == SOLVABLE_INSTALLSIZE || keyname == SOLVABLE_DISKUSAGE || keyname == SOLVABLE_FILELIST)
- continue;
- if (keyname == SOLVABLE_MEDIADIR || keyname == SOLVABLE_MEDIAFILE || keyname == SOLVABLE_MEDIANR)
- continue;
- if (keyname == SOLVABLE_DOWNLOADSIZE || keyname == SOLVABLE_CHECKSUM)
- continue;
- if (keyname == SOLVABLE_SOURCENAME || keyname == SOLVABLE_SOURCEARCH || keyname == SOLVABLE_SOURCEEVR)
- continue;
- if (keyname == SOLVABLE_PKGID || keyname == SOLVABLE_HDRID || keyname == SOLVABLE_LEADSIGID)
- continue;
- if (keyname == SUSETAGS_SHARE_NAME || keyname == SUSETAGS_SHARE_EVR || keyname == SUSETAGS_SHARE_ARCH)
- continue;
- MAPSET(&keyidmap, i);
- }
- last_found = 0;
- for (i = 0; i < pd.nshare; i++)
- {
- unsigned int n, nn;
- Solvable *found = 0;
- if (!pd.share_with[i].name)
- continue;
- for (n = repo->start, nn = repo->start + last_found; n < repo->end; n++, nn++)
- {
- if (nn >= repo->end)
- nn = repo->start;
- found = pool->solvables + nn;
- if (found->repo == repo
- && found->name == pd.share_with[i].name
- && found->evr == pd.share_with[i].evr
- && found->arch == pd.share_with[i].arch)
- {
- last_found = nn - repo->start;
- break;
- }
- }
- if (n != repo->end)
- repodata_merge_some_attrs(data, repo->start + i, repo->start + last_found, &keyidmap, 0);
- }
- free(pd.share_with);
- map_free(&keyidmap);
- }
+ process_shares(&pd);
solv_free(joinhash);
repodata_free_dircache(data);
diff --git a/ext/testcase.c b/ext/testcase.c
index 26acefa..77cc719 100644
--- a/ext/testcase.c
+++ b/ext/testcase.c
@@ -383,6 +383,7 @@ struct oplist {
{ REL_AND, "&" },
{ REL_OR , "|" },
{ REL_WITH , "+" },
+ { REL_WITHOUT , "-" },
{ REL_NAMESPACE , "<NAMESPACE>" },
{ REL_ARCH, "." },
{ REL_MULTIARCH, "<MULTIARCH>" },
@@ -392,6 +393,7 @@ struct oplist {
{ REL_KIND, "<KIND>" },
{ REL_ELSE, "<ELSE>" },
{ REL_ERROR, "<ERROR>" },
+ { REL_UNLESS, "<UNLESS>" },
{ REL_LT, "<" },
{ 0, 0 }
};
diff --git a/package/libsolv.changes b/package/libsolv.changes
index 5418084..21bdbd1 100644
--- a/package/libsolv.changes
+++ b/package/libsolv.changes
@@ -1,4 +1,15 @@
-------------------------------------------------------------------
+Thu Sep 7 16:18:20 CEST 2017 - mls@suse.de
+
+- expose solver_get_recommendations in bindings
+- fix bug in solver_prune_to_highest_prio_per_name resulting in
+ bad solver_get_recommendations output
+- support 'without' and 'unless' dependencies
+- fix yumobs rule generation bug
+- Use same heuristic as upstream to determine src rpms
+- bump version to 0.6.29
+
+-------------------------------------------------------------------
Fri Jun 30 16:37:31 CEST 2017 - mls@suse.de
- make peace with newer perl versions
diff --git a/src/cplxdeps.c b/src/cplxdeps.c
index aadbc48..6c40752 100644
--- a/src/cplxdeps.c
+++ b/src/cplxdeps.c
@@ -29,7 +29,7 @@ pool_is_complex_dep_rd(Pool *pool, Reldep *rd)
{
for (;;)
{
- if (rd->flags == REL_AND || rd->flags == REL_COND) /* those two are the complex ones */
+ if (rd->flags == REL_AND || rd->flags == REL_COND || rd->flags == REL_UNLESS) /* those two are the complex ones */
return 1;
if (rd->flags != REL_OR)
return 0;
@@ -127,6 +127,167 @@ invert_depblocks(Pool *pool, Queue *bq, int start, int r)
return -1;
}
+/* distributive property: (a1*a2 + b1*b2) * (c1*c2 + d1*d2) =
+ a1*a2*c1*c2 + a1*a2*d1*d2 + b1*b2*c1*c2 + b1*b2*d1*d2 */
+static int
+distribute_depblocks(Pool *pool, Queue *bq, int bqcnt, int bqcnt2, int flags)
+{
+ int i, j, bqcnt3;
+#ifdef CPLXDEBUG
+ printf("COMPLEX DISTRIBUTE %d %d %d\n", bqcnt, bqcnt2, bq->count);
+#endif
+ bqcnt2 = expand_simpledeps(pool, bq, bqcnt, bqcnt2);
+ bqcnt3 = bq->count;
+ for (i = bqcnt; i < bqcnt2; i++)
+ {
+ for (j = bqcnt2; j < bqcnt3; j++)
+ {
+ int a, b;
+ int bqcnt4 = bq->count;
+ int k = i;
+
+ /* mix i block with j block, both blocks are sorted */
+ while (bq->elements[k] && bq->elements[j])
+ {
+ if (bq->elements[k] < bq->elements[j])
+ queue_push(bq, bq->elements[k++]);
+ else
+ {
+ if (bq->elements[k] == bq->elements[j])
+ k++;
+ queue_push(bq, bq->elements[j++]);
+ }
+ }
+ while (bq->elements[j])
+ queue_push(bq, bq->elements[j++]);
+ while (bq->elements[k])
+ queue_push(bq, bq->elements[k++]);
+
+ /* block is finished, check for A + -A */
+ for (a = bqcnt4, b = bq->count - 1; a < b; )
+ {
+ if (-bq->elements[a] == bq->elements[b])
+ break;
+ if (-bq->elements[a] > bq->elements[b])
+ a++;
+ else
+ b--;
+ }
+ if (a < b)
+ queue_truncate(bq, bqcnt4); /* ignore this block */
+ else
+ queue_push(bq, 0); /* finish block */
+ }
+ /* advance to next block */
+ while (bq->elements[i])
+ i++;
+ }
+ queue_deleten(bq, bqcnt, bqcnt3 - bqcnt);
+ if (bqcnt == bq->count)
+ return flags & CPLXDEPS_TODNF ? 0 : 1;
+ return -1;
+}
+
+static int normalize_dep(Pool *pool, Id dep, Queue *bq, int flags);
+
+static int
+normalize_dep_or(Pool *pool, Id dep1, Id dep2, Queue *bq, int flags, int invflags)
+{
+ int r1, r2, bqcnt2, bqcnt = bq->count;
+ r1 = normalize_dep(pool, dep1, bq, flags);
+ if (r1 == 1)
+ return 1; /* early exit */
+ bqcnt2 = bq->count;
+ r2 = normalize_dep(pool, dep2, bq, flags ^ invflags);
+ if (invflags)
+ r2 = invert_depblocks(pool, bq, bqcnt2, r2);
+ if (r1 == 1 || r2 == 1)
+ {
+ queue_truncate(bq, bqcnt);
+ return 1;
+ }
+ if (r1 == 0)
+ return r2;
+ if (r2 == 0)
+ return r1;
+ if ((flags & CPLXDEPS_TODNF) == 0)
+ return distribute_depblocks(pool, bq, bqcnt, bqcnt2, flags);
+ return -1;
+}
+
+static int
+normalize_dep_and(Pool *pool, Id dep1, Id dep2, Queue *bq, int flags, int invflags)
+{
+ int r1, r2, bqcnt2, bqcnt = bq->count;
+ r1 = normalize_dep(pool, dep1, bq, flags);
+ if (r1 == 0)
+ return 0; /* early exit */
+ bqcnt2 = bq->count;
+ r2 = normalize_dep(pool, dep2, bq, flags ^ invflags);
+ if (invflags)
+ r2 = invert_depblocks(pool, bq, bqcnt2, r2);
+ if (r1 == 0 || r2 == 0)
+ {
+ queue_truncate(bq, bqcnt);
+ return 0;
+ }
+ if (r1 == 1)
+ return r2;
+ if (r2 == 1)
+ return r1;
+ if ((flags & CPLXDEPS_TODNF) != 0)
+ return distribute_depblocks(pool, bq, bqcnt, bqcnt2, flags);
+ return -1;
+}
+
+static int
+normalize_dep_if_else(Pool *pool, Id dep1, Id dep2, Id dep3, Queue *bq, int flags)
+{
+ /* A IF (B ELSE C) -> (A OR ~B) AND (C OR B) */
+ int r1, r2, bqcnt2, bqcnt = bq->count;
+ r1 = normalize_dep_or(pool, dep1, dep2, bq, flags, CPLXDEPS_TODNF);
+ if (r1 == 0)
+ return 0; /* early exit */
+ bqcnt2 = bq->count;
+ r2 = normalize_dep_or(pool, dep2, dep3, bq, flags, 0);
+ if (r1 == 0 || r2 == 0)
+ {
+ queue_truncate(bq, bqcnt);
+ return 0;
+ }
+ if (r1 == 1)
+ return r2;
+ if (r2 == 1)
+ return r1;
+ if ((flags & CPLXDEPS_TODNF) != 0)
+ return distribute_depblocks(pool, bq, bqcnt, bqcnt2, flags);
+ return -1;
+}
+
+static int
+normalize_dep_unless_else(Pool *pool, Id dep1, Id dep2, Id dep3, Queue *bq, int flags)
+{
+ /* A UNLESS (B ELSE C) -> (A AND ~B) OR (C AND B) */
+ int r1, r2, bqcnt2, bqcnt = bq->count;
+ r1 = normalize_dep_and(pool, dep1, dep2, bq, flags, CPLXDEPS_TODNF);
+ if (r1 == 1)
+ return 1; /* early exit */
+ bqcnt2 = bq->count;
+ r2 = normalize_dep_and(pool, dep2, dep3, bq, flags, 0);
+ if (r1 == 1 || r2 == 1)
+ {
+ queue_truncate(bq, bqcnt);
+ return 1;
+ }
+ if (r1 == 0)
+ return r2;
+ if (r2 == 0)
+ return r1;
+ if ((flags & CPLXDEPS_TODNF) == 0)
+ return distribute_depblocks(pool, bq, bqcnt, bqcnt2, flags);
+ return -1;
+}
+
/*
* returns:
* 0: no blocks
@@ -136,229 +297,38 @@ invert_depblocks(Pool *pool, Queue *bq, int start, int r)
static int
normalize_dep(Pool *pool, Id dep, Queue *bq, int flags)
{
- int bqcnt = bq->count;
- int bqcnt2;
- int todnf = flags & CPLXDEPS_TODNF ? 1 : 0;
Id p, dp;
+ int bqcnt;
-#ifdef CPLXDEBUG
- printf("normalize_dep %s todnf:%d\n", pool_dep2str(pool, dep), todnf);
-#endif
if (pool_is_complex_dep(pool, dep))
{
Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND)
+ if (rd->flags == REL_COND)
{
- int rdflags = rd->flags;
- Id name = rd->name;
Id evr = rd->evr;
- int r, mode;
-
- if (rdflags == REL_COND)
- {
- /* check for relly complex ELSE case */
- if (ISRELDEP(evr))
- {
- Reldep *rd2 = GETRELDEP(pool, evr);
- if (rd2->flags == REL_ELSE)
- {
- int r2;
- /* really complex case */
- if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_1)
- {
- /* A OR ~B */
- rdflags = REL_COND;
- evr = rd2->name;
- }
- else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_2)
- {
- /* C OR B */
- rdflags = REL_OR;
- name = rd2->evr;
- evr = rd2->name;
- }
- else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_1)
- {
- /* A AND B */
- rdflags = REL_AND;
- evr = rd2->name;
- }
- else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_2)
- {
- /* A AND C */
- rdflags = REL_AND;
- evr = rd2->evr;
- }
- else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_3)
- {
- /* C AND ~B */
- rdflags = REL_ELSE;
- name = rd2->evr;
- evr = rd2->name;
- }
- else if (!todnf)
- {
- /* we want AND: A IF (B ELSE C) -> (A OR ~B) AND (C OR B) */
- r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_1);
- if (r == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
- return 0;
- r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_2);
- if (r2 == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
- {
- queue_truncate(bq, bqcnt);
- return 0;
- }
- if (r == -1 || r2 == -1)
- return -1;
- return r == 1 || r2 == 1 ? 1 : 0;
- }
- else
- {
- int r2, r3;
- /* we want OR: A IF (B ELSE C) -> (A AND B) OR (A AND C) OR (~B AND C) */
- r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_1);
- if (r == 1)
- return 1;
- r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_2);
- if (r2 == 1)
- {
- queue_truncate(bq, bqcnt);
- return 1;
- }
- r3 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_3);
- if (r3 == 1)
- {
- queue_truncate(bq, bqcnt);
- return 1;
- }
- if (r == -1 || r2 == -1 || r3 == -1)
- return -1;
- return 0;
- }
- }
- }
- }
- mode = rdflags == REL_AND || rdflags == REL_ELSE ? 0 : 1;
-
- /* get blocks of first argument */
- r = normalize_dep(pool, name, bq, flags);
- if (r == 0)
- {
- if (rdflags == REL_ELSE)
- return 0;
- if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) == 0)
- return 0;
- if (rdflags == REL_COND)
- {
- r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
- return invert_depblocks(pool, bq, bqcnt, r); /* invert block for COND */
- }
- return normalize_dep(pool, evr, bq, flags);
- }
- if (r == 1)
- {
- if (rdflags == REL_ELSE)
- {
- r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
- return invert_depblocks(pool, bq, bqcnt, r); /* invert block for ELSE */
- }
- if (rdflags == REL_OR || rdflags == REL_COND)
- return 1;
- return normalize_dep(pool, evr, bq, flags);
- }
-
- /* get blocks of second argument */
- bqcnt2 = bq->count;
- /* COND is OR with NEG on evr block, so we invert the todnf flag in that case */
- r = normalize_dep(pool, evr, bq, rdflags == REL_COND || rdflags == REL_ELSE ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags);
- if (rdflags == REL_COND || rdflags == REL_ELSE)
- r = invert_depblocks(pool, bq, bqcnt2, r); /* invert 2nd block */
- if (r == 0)
+ if (ISRELDEP(evr))
{
- if (rdflags == REL_OR)
- return -1;
- if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) != 0)
- return -1;
- queue_truncate(bq, bqcnt);
- return 0;
- }
- if (r == 1)
- {
- if (rdflags == REL_COND || rdflags == REL_OR)
- {
- queue_truncate(bq, bqcnt);
- return 1;
- }
- return -1;
- }
- if (mode == todnf)
- {
- /* simple case: just join em. nothing more to do here. */
-#ifdef CPLXDEBUG
- printf("SIMPLE JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count);
-#endif
- return -1;
+ Reldep *rd2 = GETRELDEP(pool, evr);
+ if (rd2->flags == REL_ELSE)
+ return normalize_dep_if_else(pool, rd->name, rd2->name, rd2->evr, bq, flags);
}
- else
+ return normalize_dep_or(pool, rd->name, rd->evr, bq, flags, CPLXDEPS_TODNF);
+ }
+ if (rd->flags == REL_UNLESS)
+ {
+ Id evr = rd->evr;
+ if (ISRELDEP(evr))
{
- /* complex case: mix em */
- int i, j, bqcnt3;
-#ifdef CPLXDEBUG
- printf("COMPLEX JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count);
-#endif
- bqcnt2 = expand_simpledeps(pool, bq, bqcnt, bqcnt2);
- bqcnt3 = bq->count;
- for (i = bqcnt; i < bqcnt2; i++)
- {
- for (j = bqcnt2; j < bqcnt3; j++)
- {
- int a, b;
- int bqcnt4 = bq->count;
- int k = i;
-
- /* mix i block with j block, both blocks are sorted */
- while (bq->elements[k] && bq->elements[j])
- {
- if (bq->elements[k] < bq->elements[j])
- queue_push(bq, bq->elements[k++]);
- else
- {
- if (bq->elements[k] == bq->elements[j])
- k++;
- queue_push(bq, bq->elements[j++]);
- }
- }
- while (bq->elements[j])
- queue_push(bq, bq->elements[j++]);
- while (bq->elements[k])
- queue_push(bq, bq->elements[k++]);
-
- /* block is finished, check for A + -A */
- for (a = bqcnt4, b = bq->count - 1; a < b; )
- {
- if (-bq->elements[a] == bq->elements[b])
- break;
- if (-bq->elements[a] > bq->elements[b])
- a++;
- else
- b--;
- }
- if (a < b)
- queue_truncate(bq, bqcnt4); /* ignore this block */
- else
- queue_push(bq, 0); /* finish block */
- }
- /* advance to next block */
- while (bq->elements[i])
- i++;
- }
- i = -1;
- if (bqcnt3 == bq->count) /* ignored all blocks? */
- i = todnf ? 0 : 1;
- queue_deleten(bq, bqcnt, bqcnt3 - bqcnt);
- return i;
+ Reldep *rd2 = GETRELDEP(pool, evr);
+ if (rd2->flags == REL_ELSE)
+ return normalize_dep_unless_else(pool, rd->name, rd2->name, rd2->evr, bq, flags);
}
+ return normalize_dep_and(pool, rd->name, rd->evr, bq, flags, CPLXDEPS_TODNF);
}
+ if (rd->flags == REL_OR)
+ return normalize_dep_or(pool, rd->name, rd->evr, bq, flags, 0);
+ if (rd->flags == REL_AND)
+ return normalize_dep_and(pool, rd->name, rd->evr, bq, flags, 0);
}
/* fallback case: just use package list */
@@ -375,11 +345,11 @@ normalize_dep(Pool *pool, Id dep, Queue *bq, int flags)
if (!pool_match_nevr(pool, pool->solvables + p, dep))
continue;
queue_push(bq, p);
- if (todnf)
+ if ((flags & CPLXDEPS_TODNF) != 0)
queue_push(bq, 0);
}
}
- else if (todnf)
+ else if ((flags & CPLXDEPS_TODNF) != 0)
{
while ((p = pool->whatprovidesdata[dp++]) != 0)
queue_push2(bq, p, 0);
@@ -388,7 +358,7 @@ normalize_dep(Pool *pool, Id dep, Queue *bq, int flags)
queue_push2(bq, pool->nsolvables, dp); /* not yet expanded marker + offset */
if (bq->count == bqcnt)
return 0; /* no provider */
- if (!todnf)
+ if (!(flags & CPLXDEPS_TODNF))
queue_push(bq, 0); /* finish block */
return -1;
}
@@ -423,11 +393,11 @@ pool_add_pos_literals_complex_dep(Pool *pool, Id dep, Queue *q, Map *m, int neg)
while (ISRELDEP(dep))
{
Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags != REL_AND && rd->flags != REL_OR && rd->flags != REL_COND)
+ if (rd->flags != REL_AND && rd->flags != REL_OR && rd->flags != REL_COND && rd->flags != REL_UNLESS)
break;
pool_add_pos_literals_complex_dep(pool, rd->name, q, m, neg);
dep = rd->evr;
- if (rd->flags == REL_COND)
+ if (rd->flags == REL_COND || rd->flags == REL_UNLESS)
{
neg = !neg;
if (ISRELDEP(dep))
diff --git a/src/cplxdeps.h b/src/cplxdeps.h
index 798b485..7c5946a 100644
--- a/src/cplxdeps.h
+++ b/src/cplxdeps.h
@@ -35,12 +35,5 @@ extern void pool_add_pos_literals_complex_dep(Pool *pool, Id dep, Queue *q, Map
#define CPLXDEPS_NAME (1 << 3)
#define CPLXDEPS_DONTFIX (1 << 4)
-#define CPLXDEPS_ELSE_AND_1 (1 << 8)
-#define CPLXDEPS_ELSE_AND_2 (1 << 9)
-#define CPLXDEPS_ELSE_OR_1 (1 << 10)
-#define CPLXDEPS_ELSE_OR_2 (1 << 11)
-#define CPLXDEPS_ELSE_OR_3 (1 << 12)
-#define CPLXDEPS_ELSE_MASK (0x1f00)
-
#endif
diff --git a/src/policy.c b/src/policy.c
index a6d3441..468be67 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -202,14 +202,14 @@ solver_prune_to_highest_prio_per_name(Solver *solv, Queue *plist)
{
if (pool->solvables[plist->elements[i]].name != name)
{
+ name = pool->solvables[plist->elements[i]].name;
if (pq.count > 2)
solver_prune_to_highest_prio(solv, &pq);
for (k = 0; k < pq.count; k++)
plist->elements[j++] = pq.elements[k];
queue_empty(&pq);
- queue_push(&pq, plist->elements[i]);
- name = pool->solvables[pq.elements[0]].name;
}
+ queue_push(&pq, plist->elements[i]);
}
if (pq.count > 2)
solver_prune_to_highest_prio(solv, &pq);
diff --git a/src/pool.c b/src/pool.c
index bd97026..b596ace 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -705,6 +705,10 @@ pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
if (!pool_match_nevr(pool, s, name))
return 0;
return pool_match_nevr(pool, s, evr);
+ case REL_WITHOUT:
+ if (!pool_match_nevr(pool, s, name))
+ return 0;
+ return !pool_match_nevr(pool, s, evr);
case REL_MULTIARCH:
if (evr != ARCH_ANY)
return 0;
@@ -818,17 +822,17 @@ pool_match_dep(Pool *pool, Id d1, Id d2)
{
/* we use potentially matches for complex deps */
rd1 = GETRELDEP(pool, d1);
- if (rd1->flags == REL_AND || rd1->flags == REL_OR || rd1->flags == REL_WITH || rd1->flags == REL_COND)
+ if (rd1->flags == REL_AND || rd1->flags == REL_OR || rd1->flags == REL_WITH || rd1->flags == REL_WITHOUT || rd1->flags == REL_COND || rd1->flags == REL_UNLESS)
{
if (pool_match_dep(pool, rd1->name, d2))
return 1;
- if (rd1->flags == REL_COND && ISRELDEP(rd1->evr))
+ if ((rd1->flags == REL_COND || rd1->flags == REL_UNLESS) && ISRELDEP(rd1->evr))
{
rd1 = GETRELDEP(pool, rd1->evr);
if (rd1->flags != REL_ELSE)
return 0;
}
- if (rd1->flags != REL_COND && pool_match_dep(pool, rd1->evr, d2))
+ if (rd1->flags != REL_COND && rd1->flags != REL_UNLESS && rd1->flags != REL_WITHOUT && pool_match_dep(pool, rd1->evr, d2))
return 1;
return 0;
}
@@ -837,17 +841,17 @@ pool_match_dep(Pool *pool, Id d1, Id d2)
{
/* we use potentially matches for complex deps */
rd2 = GETRELDEP(pool, d2);
- if (rd2->flags == REL_AND || rd2->flags == REL_OR || rd2->flags == REL_WITH || rd2->flags == REL_COND)
+ if (rd2->flags == REL_AND || rd2->flags == REL_OR || rd2->flags == REL_WITH || rd2->flags == REL_WITHOUT || rd2->flags == REL_COND || rd2->flags == REL_UNLESS)
{
if (pool_match_dep(pool, d1, rd2->name))
return 1;
- if (rd2->flags == REL_COND && ISRELDEP(rd2->evr))
+ if ((rd2->flags == REL_COND || rd2->flags == REL_UNLESS) && ISRELDEP(rd2->evr))
{
rd2 = GETRELDEP(pool, rd2->evr);
if (rd2->flags != REL_ELSE)
return 0;
}
- if (rd2->flags != REL_COND && pool_match_dep(pool, d1, rd2->evr))
+ if (rd2->flags != REL_COND && rd2->flags != REL_UNLESS && rd2->flags != REL_WITHOUT && pool_match_dep(pool, d1, rd2->evr))
return 1;
return 0;
}
@@ -1108,11 +1112,26 @@ pool_addrelproviders(Pool *pool, Id d)
wp = 0;
}
break;
-
+ case REL_WITHOUT:
+ wp = pool_whatprovides(pool, name);
+ pp2 = pool_whatprovides_ptr(pool, evr);
+ pp = pool->whatprovidesdata + wp;
+ while ((p = *pp++) != 0)
+ {
+ for (pp3 = pp2; *pp3; pp3++)
+ if (*pp3 == p)
+ break;
+ if (!*pp3)
+ queue_push(&plist, p); /* use it */
+ else
+ wp = 0;
+ }
+ break;
case REL_AND:
case REL_OR:
case REL_COND:
- if (flags == REL_COND)
+ case REL_UNLESS:
+ if (flags == REL_COND || flags == REL_UNLESS)
{
if (ISRELDEP(evr))
{
diff --git a/src/pool.h b/src/pool.h
index 3eeea06..f6a5493 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -223,12 +223,14 @@ struct _Pool {
#define REL_NAMESPACE 19
#define REL_ARCH 20
#define REL_FILECONFLICT 21
-#define REL_COND 22
+#define REL_COND 22 /* OR_NOT */
#define REL_COMPAT 23
#define REL_KIND 24 /* for filters only */
#define REL_MULTIARCH 25 /* debian multiarch annotation */
-#define REL_ELSE 26 /* only as evr part of REL_COND */
+#define REL_ELSE 26 /* only as evr part of REL_COND/REL_UNLESS */
#define REL_ERROR 27 /* parse errors and the like */
+#define REL_WITHOUT 28
+#define REL_UNLESS 29 /* AND_NOT */
#if !defined(__GNUC__) && !defined(__attribute__)
# define __attribute__(x)
@@ -398,11 +400,6 @@ void pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts);
continue; \
else
-#ifdef ENABLE_COMPS
-#define ISCONDDEP(id) (ISRELDEP(id) && (GETRELDEP(pool, id))->flags == REL_COND)
-#define MODIFYCONDDEP(id, tst) do { Reldep *condrd = GETRELDEP(pool, id); Id condp, condpp; FOR_PROVIDES(condrd->evr, condp, condpp) if (tst) break; id = condp ? condrd->name : 0;} while(0)
-#endif
-
#define POOL_DEBUG(type, ...) do {if ((pool->debugmask & (type)) != 0) pool_debug(pool, (type), __VA_ARGS__);} while (0)
#define IF_POOLDEBUG(type) if ((pool->debugmask & (type)) != 0)
diff --git a/src/poolid.c b/src/poolid.c
index 3a8a3c8..bb8d4f6 100644
--- a/src/poolid.c
+++ b/src/poolid.c
@@ -178,6 +178,8 @@ pool_id2rel(const Pool *pool, Id id)
return pool->disttype == DISTTYPE_RPM ? " or " : " | ";
case REL_WITH:
return pool->disttype == DISTTYPE_RPM ? " with " : " + ";
+ case REL_WITHOUT:
+ return pool->disttype == DISTTYPE_RPM ? " without " : " - ";
case REL_NAMESPACE:
return " NAMESPACE "; /* actually not used in dep2str */
case REL_ARCH:
@@ -188,6 +190,8 @@ pool_id2rel(const Pool *pool, Id id)
return " FILECONFLICT ";
case REL_COND:
return pool->disttype == DISTTYPE_RPM ? " if " : " IF ";
+ case REL_UNLESS:
+ return pool->disttype == DISTTYPE_RPM ? " unless " : " UNLESS ";
case REL_COMPAT:
return " compat >= ";
case REL_KIND:
@@ -238,9 +242,9 @@ dep2strcpy(const Pool *pool, char *p, Id id, int oldrel)
{
Reldep *rd = GETRELDEP(pool, id);
int rel = rd->flags;
- if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH || oldrel == REL_COND || oldrel == REL_ELSE || oldrel == -1)
- if (rel == REL_AND || rel == REL_OR || rel == REL_WITH || rel == REL_COND || rel == REL_ELSE)
- if ((oldrel != rel || rel == REL_COND || rel == REL_ELSE) && !(oldrel == REL_COND && rel == REL_ELSE))
+ if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH || oldrel == REL_WITHOUT || oldrel == REL_COND || oldrel == REL_UNLESS || oldrel == REL_ELSE || oldrel == -1)
+ if (rel == REL_AND || rel == REL_OR || rel == REL_WITH || rel == REL_WITHOUT || rel == REL_COND || rel == REL_UNLESS || rel == REL_ELSE)
+ if ((oldrel != rel || rel == REL_COND || rel == REL_UNLESS || rel == REL_ELSE) && !((oldrel == REL_COND || oldrel == REL_UNLESS) && rel == REL_ELSE))
{
*p++ = '(';
dep2strcpy(pool, p, rd->name, rd->flags);
diff --git a/src/rules.c b/src/rules.c
index 26b93ea..5654330 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -52,7 +52,7 @@ dep_possible(Solver *solv, Id dep, Map *m)
Reldep *rd = GETRELDEP(pool, dep);
if (rd->flags >= 8)
{
- if (rd->flags == REL_COND)
+ if (rd->flags == REL_COND || rd->flags == REL_UNLESS)
return 1;
if (rd->flags == REL_AND)
{
@@ -3720,7 +3720,6 @@ solver_addyumobsrules(Solver *solv)
#if 0
printf("checking yumobs for %s\n", pool_solvable2str(pool, s));
#endif
- queue_empty(&qo);
for (opp = solv->obsoletes_data + solv->obsoletes[p - installed->start]; (op = *opp++) != 0;)
{
Solvable *os = pool->solvables + op;
diff --git a/src/selection.c b/src/selection.c
index 37c6184..16fe3a7 100644
--- a/src/selection.c
+++ b/src/selection.c
@@ -890,17 +890,17 @@ matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
if (ISRELDEP(id))
{
Reldep *rd = GETRELDEP(pool, id);
- if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH || rd->flags == REL_COND)
+ if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH || rd->flags == REL_WITHOUT || rd->flags == REL_COND || rd->flags == REL_UNLESS)
{
if (matchdep(pool, rd->name, rname, rflags, revr, flags))
return 1;
- if (rd->flags == REL_COND && ISRELDEP(rd->evr))
+ if ((rd->flags == REL_COND || rd->flags == REL_UNLESS) && ISRELDEP(rd->evr))
{
rd = GETRELDEP(pool, rd->evr);
if (rd->flags != REL_ELSE)
return 0;
}
- if (rd->flags != REL_COND && matchdep(pool, rd->evr, rname, rflags, revr, flags))
+ if (rd->flags != REL_COND && rd->flags != REL_UNLESS && rd->flags != REL_WITHOUT && matchdep(pool, rd->evr, rname, rflags, revr, flags))
return 1;
return 0;
}
diff --git a/src/solver.c b/src/solver.c
index bec1d9f..5d1052d 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -104,6 +104,57 @@ solver_splitprovides(Solver *solv, Id dep, Map *m)
return 0;
}
+int
+solver_dep_fulfilled_cplx(Solver *solv, Reldep *rd)
+{
+ Pool *pool = solv->pool;
+ if (rd->flags == REL_COND)
+ {
+ if (ISRELDEP(rd->evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, rd->evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ if (solver_dep_fulfilled(solv, rd2->name))
+ return solver_dep_fulfilled(solv, rd->name);
+ return solver_dep_fulfilled(solv, rd2->evr);
+ }
+ }
+ if (solver_dep_fulfilled(solv, rd->name))
+ return 1;
+ return !solver_dep_fulfilled(solv, rd->evr);
+ }
+ if (rd->flags == REL_UNLESS)
+ {
+ if (ISRELDEP(rd->evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, rd->evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ if (!solver_dep_fulfilled(solv, rd2->name))
+ return solver_dep_fulfilled(solv, rd->name);
+ return solver_dep_fulfilled(solv, rd2->evr);
+ }
+ }
+ if (!solver_dep_fulfilled(solv, rd->name))
+ return 0;
+ return !solver_dep_fulfilled(solv, rd->evr);
+ }
+ if (rd->flags == REL_AND)
+ {
+ if (!solver_dep_fulfilled(solv, rd->name))
+ return 0;
+ return solver_dep_fulfilled(solv, rd->evr);
+ }
+ if (rd->flags == REL_OR)
+ {
+ if (solver_dep_fulfilled(solv, rd->name))
+ return 1;
+ return solver_dep_fulfilled(solv, rd->evr);
+ }
+ return 0;
+}
+
/* mirrors solver_dep_fulfilled, but returns 2 if a new package
* was involved */
@@ -140,6 +191,30 @@ solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep)
return 0;
return r1 == 2 ? 2 : 1;
}
+ if (rd->flags == REL_UNLESS)
+ {
+ int r1, r2;
+ if (ISRELDEP(rd->evr))
+ {
+ Reldep *rd2 = GETRELDEP(pool, rd->evr);
+ if (rd2->flags == REL_ELSE)
+ {
+ r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->name);
+ if (r1)
+ {
+ r2 = solver_dep_fulfilled_alreadyinstalled(solv, rd2->evr);
+ return r2 && r1 == 2 ? 2 : r2;
+ }
+ return solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
+ }
+ }
+ /* A AND NOT(B) */
+ r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
+ r2 = !solver_dep_fulfilled_alreadyinstalled(solv, rd->evr);
+ if (!r1 || !r2)
+ return 0;
+ return r1 == 2 ? 2 : 1;
+ }
if (rd->flags == REL_AND)
{
int r2, r1 = solver_dep_fulfilled_alreadyinstalled(solv, rd->name);
diff --git a/src/solver_private.h b/src/solver_private.h
index fe80881..a234223 100644
--- a/src/solver_private.h
+++ b/src/solver_private.h
@@ -17,6 +17,7 @@ extern void solver_run_sat(Solver *solv, int disablerules, int doweak);
extern void solver_reset(Solver *solv);
extern int solver_splitprovides(Solver *solv, Id dep, Map *m);
+extern int solver_dep_fulfilled_cplx(Solver *solv, Reldep *rd);
static inline int
solver_dep_fulfilled(Solver *solv, Id dep)
@@ -27,34 +28,8 @@ solver_dep_fulfilled(Solver *solv, Id dep)
if (ISRELDEP(dep))
{
Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags == REL_COND)
- {
- if (ISRELDEP(rd->evr))
- {
- Reldep *rd2 = GETRELDEP(pool, rd->evr);
- if (rd2->flags == REL_ELSE)
- {
- if (solver_dep_fulfilled(solv, rd2->name))
- return solver_dep_fulfilled(solv, rd->name);
- return solver_dep_fulfilled(solv, rd2->evr);
- }
- }
- if (solver_dep_fulfilled(solv, rd->name))
- return 1;
- return !solver_dep_fulfilled(solv, rd->evr);
- }
- if (rd->flags == REL_AND)
- {
- if (!solver_dep_fulfilled(solv, rd->name))
- return 0;
- return solver_dep_fulfilled(solv, rd->evr);
- }
- if (rd->flags == REL_OR)
- {
- if (solver_dep_fulfilled(solv, rd->name))
- return 1;
- return solver_dep_fulfilled(solv, rd->evr);
- }
+ if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR)
+ return solver_dep_fulfilled_cplx(solv, rd);
if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
return solver_splitprovides(solv, rd->evr, 0);
}
diff --git a/test/testcases/cplxdeps/and.t b/test/testcases/cplxdeps/and.t
new file mode 100644
index 0000000..d4ef47e
--- /dev/null
+++ b/test/testcases/cplxdeps/and.t
@@ -0,0 +1,39 @@
+feature complex_deps
+repo available 0 testtags <inline>
+#>=Pkg: A1 1 1 x86_64
+#>=Prv: A
+#>=Pkg: A2 1 1 x86_64
+#>=Prv: A
+#>=Pkg: B1 1 1 x86_64
+#>=Prv: B
+#>=Pkg: B2 1 1 x86_64
+#>=Prv: B
+#>=Pkg: X 1 1 x86_64
+#>=Req: A & B
+#>=Pkg: Y 1 1 x86_64
+#>=Con: A & B
+job install name X
+result rules <inline>
+#>rule job 3986285ed3e7fa05cb3367ca1e7f0d3d X-1-1.x86_64@available
+#>rule pkg 8d94817282778a96505d2865a9b6c417 B1-1-1.x86_64@available
+#>rule pkg 8d94817282778a96505d2865a9b6c417 B2-1-1.x86_64@available
+#>rule pkg 8d94817282778a96505d2865a9b6c417 -X-1-1.x86_64@available
+#>rule pkg 9294f4d070a449a787a945d757c853ac A1-1-1.x86_64@available
+#>rule pkg 9294f4d070a449a787a945d757c853ac A2-1-1.x86_64@available
+#>rule pkg 9294f4d070a449a787a945d757c853ac -X-1-1.x86_64@available
+nextjob
+job install name Y
+result rules <inline>
+#>rule job 181d7955b2179c4ffdffedf0198f4807 Y-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -A1-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -B2-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -Y-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -A2-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -B2-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -Y-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -A1-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -B1-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -Y-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -A2-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -B1-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -Y-1-1.x86_64@available
diff --git a/test/testcases/cplxdeps/andor.t b/test/testcases/cplxdeps/andor.t
new file mode 100644
index 0000000..f60745d
--- /dev/null
+++ b/test/testcases/cplxdeps/andor.t
@@ -0,0 +1,73 @@
+feature complex_deps
+repo available 0 testtags <inline>
+#>=Pkg: A1 1 1 x86_64
+#>=Prv: A
+#>=Pkg: A2 1 1 x86_64
+#>=Prv: A
+#>=Pkg: B1 1 1 x86_64
+#>=Prv: B
+#>=Pkg: B2 1 1 x86_64
+#>=Prv: B
+#>=Pkg: C1 1 1 x86_64
+#>=Prv: C
+#>=Pkg: C2 1 1 x86_64
+#>=Prv: C
+#>=Pkg: D1 1 1 x86_64
+#>=Prv: D
+#>=Pkg: D2 1 1 x86_64
+#>=Prv: D
+#>=Pkg: X 1 1 x86_64
+#>=Req: (A & B) | (C & D)
+#>=Pkg: Y 1 1 x86_64
+#>=Con: (A & B) | (C & D)
+job install name X
+result rules <inline>
+#>rule job 3986285ed3e7fa05cb3367ca1e7f0d3d X-1-1.x86_64@available
+#>rule pkg 500f33fd32c5be8fb62896b334f580e7 B1-1-1.x86_64@available
+#>rule pkg 500f33fd32c5be8fb62896b334f580e7 B2-1-1.x86_64@available
+#>rule pkg 500f33fd32c5be8fb62896b334f580e7 D1-1-1.x86_64@available
+#>rule pkg 500f33fd32c5be8fb62896b334f580e7 D2-1-1.x86_64@available
+#>rule pkg 500f33fd32c5be8fb62896b334f580e7 -X-1-1.x86_64@available
+#>rule pkg 551b370e0a9430e9fcb2608b73b2d6f1 A1-1-1.x86_64@available
+#>rule pkg 551b370e0a9430e9fcb2608b73b2d6f1 A2-1-1.x86_64@available
+#>rule pkg 551b370e0a9430e9fcb2608b73b2d6f1 D1-1-1.x86_64@available
+#>rule pkg 551b370e0a9430e9fcb2608b73b2d6f1 D2-1-1.x86_64@available
+#>rule pkg 551b370e0a9430e9fcb2608b73b2d6f1 -X-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a B1-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a B2-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a C1-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a C2-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a -X-1-1.x86_64@available
+#>rule pkg e524681ade2cf622db027a5d989023c4 A1-1-1.x86_64@available
+#>rule pkg e524681ade2cf622db027a5d989023c4 A2-1-1.x86_64@available
+#>rule pkg e524681ade2cf622db027a5d989023c4 C1-1-1.x86_64@available
+#>rule pkg e524681ade2cf622db027a5d989023c4 C2-1-1.x86_64@available
+#>rule pkg e524681ade2cf622db027a5d989023c4 -X-1-1.x86_64@available
+nextjob
+job install name Y
+result rules <inline>
+#>rule job 181d7955b2179c4ffdffedf0198f4807 Y-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -A1-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -B2-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -Y-1-1.x86_64@available
+#>rule pkg 57f43a628a3173b517f444966e291dcc -C2-1-1.x86_64@available
+#>rule pkg 57f43a628a3173b517f444966e291dcc -D2-1-1.x86_64@available
+#>rule pkg 57f43a628a3173b517f444966e291dcc -Y-1-1.x86_64@available
+#>rule pkg 61248d82dae65a4a486fc7321a4e50ac -C2-1-1.x86_64@available
+#>rule pkg 61248d82dae65a4a486fc7321a4e50ac -D1-1-1.x86_64@available
+#>rule pkg 61248d82dae65a4a486fc7321a4e50ac -Y-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -A2-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -B2-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -Y-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -A1-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -B1-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -Y-1-1.x86_64@available
+#>rule pkg 919596a70a75b1cdd73c596397bf70e7 -C1-1-1.x86_64@available
+#>rule pkg 919596a70a75b1cdd73c596397bf70e7 -D2-1-1.x86_64@available
+#>rule pkg 919596a70a75b1cdd73c596397bf70e7 -Y-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -A2-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -B1-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -Y-1-1.x86_64@available
+#>rule pkg da2fe506ceca44a0c6eafab14af37505 -C1-1-1.x86_64@available
+#>rule pkg da2fe506ceca44a0c6eafab14af37505 -D1-1-1.x86_64@available
+#>rule pkg da2fe506ceca44a0c6eafab14af37505 -Y-1-1.x86_64@available
diff --git a/test/testcases/cplxdeps/if.t b/test/testcases/cplxdeps/if.t
new file mode 100644
index 0000000..7e3dead
--- /dev/null
+++ b/test/testcases/cplxdeps/if.t
@@ -0,0 +1,36 @@
+feature complex_deps
+repo available 0 testtags <inline>
+#>=Pkg: A1 1 1 x86_64
+#>=Prv: A
+#>=Pkg: A2 1 1 x86_64
+#>=Prv: A
+#>=Pkg: B1 1 1 x86_64
+#>=Prv: B
+#>=Pkg: B2 1 1 x86_64
+#>=Prv: B
+#>=Pkg: X 1 1 x86_64
+#>=Req: A <IF> B
+#>=Pkg: Y 1 1 x86_64
+#>=Con: A <IF> B
+job install name X
+result rules <inline>
+#>rule job 3986285ed3e7fa05cb3367ca1e7f0d3d X-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 A1-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 A2-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 -B1-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 -X-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 A1-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 A2-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 -B2-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 -X-1-1.x86_64@available
+nextjob
+job install name Y
+result rules <inline>
+#>rule job 181d7955b2179c4ffdffedf0198f4807 Y-1-1.x86_64@available
+#>rule pkg 0fd77d3093bfb9bc85606ae155bee7e0 -A1-1-1.x86_64@available
+#>rule pkg 0fd77d3093bfb9bc85606ae155bee7e0 -Y-1-1.x86_64@available
+#>rule pkg 45e18ba2f65a39574c1f4b1c77b565ec -A2-1-1.x86_64@available
+#>rule pkg 45e18ba2f65a39574c1f4b1c77b565ec -Y-1-1.x86_64@available
+#>rule pkg 88a787532b7e170c57d67c5123982b0d B1-1-1.x86_64@available
+#>rule pkg 88a787532b7e170c57d67c5123982b0d B2-1-1.x86_64@available
+#>rule pkg 88a787532b7e170c57d67c5123982b0d -Y-1-1.x86_64@available
diff --git a/test/testcases/cplxdeps/ifelse.t b/test/testcases/cplxdeps/ifelse.t
new file mode 100644
index 0000000..ef5bab9
--- /dev/null
+++ b/test/testcases/cplxdeps/ifelse.t
@@ -0,0 +1,70 @@
+feature complex_deps
+repo available 0 testtags <inline>
+#>=Pkg: A1 1 1 x86_64
+#>=Prv: A
+#>=Pkg: A2 1 1 x86_64
+#>=Prv: A
+#>=Pkg: B1 1 1 x86_64
+#>=Prv: B
+#>=Pkg: B2 1 1 x86_64
+#>=Prv: B
+#>=Pkg: C1 1 1 x86_64
+#>=Prv: C
+#>=Pkg: C2 1 1 x86_64
+#>=Prv: C
+#>=Pkg: X 1 1 x86_64
+#>=Req: A <IF> (B <ELSE> C)
+#>=Pkg: Y 1 1 x86_64
+#>=Con: A <IF> (B <ELSE> C)
+job install name X
+result rules <inline>
+#>rule job 3986285ed3e7fa05cb3367ca1e7f0d3d X-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 A1-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 A2-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 -B1-1-1.x86_64@available
+#>rule pkg 2c561cfd067b5ec806fd5c4fcd2ac761 -X-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 A1-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 A2-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 -B2-1-1.x86_64@available
+#>rule pkg 72c9298b01fec76aae2722e2cdfdc776 -X-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a B1-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a B2-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a C1-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a C2-1-1.x86_64@available
+#>rule pkg dee60af94c8ea49c9f99362dcb65806a -X-1-1.x86_64@available
+nextjob
+job install name Y
+result rules <inline>
+#>rule job 181d7955b2179c4ffdffedf0198f4807 Y-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -A1-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -B2-1-1.x86_64@available
+#>rule pkg 05a449a52d4792a0b847f482f5d7b509 -Y-1-1.x86_64@available
+#>rule pkg 2823a39a3d1ae2f7d45ca97e97f5bf8e -A1-1-1.x86_64@available
+#>rule pkg 2823a39a3d1ae2f7d45ca97e97f5bf8e -C1-1-1.x86_64@available
+#>rule pkg 2823a39a3d1ae2f7d45ca97e97f5bf8e -Y-1-1.x86_64@available
+#>rule pkg 46a6ab5f0c299f23867d74570cc179b8 B1-1-1.x86_64@available
+#>rule pkg 46a6ab5f0c299f23867d74570cc179b8 B2-1-1.x86_64@available
+#>rule pkg 46a6ab5f0c299f23867d74570cc179b8 -C1-1-1.x86_64@available
+#>rule pkg 46a6ab5f0c299f23867d74570cc179b8 -Y-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -A2-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -B2-1-1.x86_64@available
+#>rule pkg 85eac3dcd30bb5f51ad50b6644455822 -Y-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -A1-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -B1-1-1.x86_64@available
+#>rule pkg 8611a3d851adbd063a5d34a3ad4804e6 -Y-1-1.x86_64@available
+#>rule pkg 92d66d3ad45eaa7d443a05245c9a0eaf -A2-1-1.x86_64@available
+#>rule pkg 92d66d3ad45eaa7d443a05245c9a0eaf -C1-1-1.x86_64@available
+#>rule pkg 92d66d3ad45eaa7d443a05245c9a0eaf -Y-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -A2-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -B1-1-1.x86_64@available
+#>rule pkg ba6ba0db8d7421f83f7df6cc4df6df7d -Y-1-1.x86_64@available
+#>rule pkg c3f6b37277eb48011d0e68c11323ea3e B1-1-1.x86_64@available
+#>rule pkg c3f6b37277eb48011d0e68c11323ea3e B2-1-1.x86_64@available
+#>rule pkg c3f6b37277eb48011d0e68c11323ea3e -C2-1-1.x86_64@available
+#>rule pkg c3f6b37277eb48011d0e68c11323ea3e -Y-1-1.x86_64@available
+#>rule pkg c450fe9f8321047ee2cd1e6fc9f34df6 -A2-1-1.x86_64@available
+#>rule pkg c450fe9f8321047ee2cd1e6fc9f34df6 -C2-1-1.x86_64@available
+#>rule pkg c450fe9f8321047ee2cd1e6fc9f34df6 -Y-1-1.x86_64@available
+#>rule pkg da9eb4921698e87f788a89bd25cf75b8 -A1-1-1.x86_64@available
+#>rule pkg da9eb4921698e87f788a89bd25cf75b8 -C2-1-1.x86_64@available
+#>rule pkg da9eb4921698e87f788a89bd25cf75b8 -Y-1-1.x86_64@available
diff --git a/test/testcases/cplxdeps/or.t b/test/testcases/cplxdeps/or.t
new file mode 100644
index 0000000..7446799
--- /dev/null
+++ b/test/testcases/cplxdeps/or.t
@@ -0,0 +1,34 @@
+feature complex_deps
+repo available 0 testtags <inline>
+#>=Pkg: A1 1 1 x86_64
+#>=Prv: A
+#>=Pkg: A2 1 1 x86_64
+#>=Prv: A
+#>=Pkg: B1 1 1 x86_64
+#>=Prv: B
+#>=Pkg: B2 1 1 x86_64
+#>=Prv: B
+#>=Pkg: X 1 1 x86_64
+#>=Req: A | B
+#>=Pkg: Y 1 1 x86_64
+#>=Con: A | B
+job install name X
+result rules <inline>
+#>rule job 3986285ed3e7fa05cb3367ca1e7f0d3d X-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 A1-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 A2-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 B1-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 B2-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 -X-1-1.x86_64@available
+nextjob
+job install name Y
+result rules <inline>
+#>rule job 181d7955b2179c4ffdffedf0198f4807 Y-1-1.x86_64@available
+#>rule pkg 0fd77d3093bfb9bc85606ae155bee7e0 -A1-1-1.x86_64@available
+#>rule pkg 0fd77d3093bfb9bc85606ae155bee7e0 -Y-1-1.x86_64@available
+#>rule pkg 45e18ba2f65a39574c1f4b1c77b565ec -A2-1-1.x86_64@available
+#>rule pkg 45e18ba2f65a39574c1f4b1c77b565ec -Y-1-1.x86_64@available
+#>rule pkg 69d83d7a676b6a65f79a6fc5bcf2ca6e -B1-1-1.x86_64@available
+#>rule pkg 69d83d7a676b6a65f79a6fc5bcf2ca6e -Y-1-1.x86_64@available
+#>rule pkg d6e57752cc50ab9fc0a218fda6dbf172 -B2-1-1.x86_64@available
+#>rule pkg d6e57752cc50ab9fc0a218fda6dbf172 -Y-1-1.x86_64@available
diff --git a/test/testcases/cplxdeps/orand.t b/test/testcases/cplxdeps/orand.t
new file mode 100644
index 0000000..8a5108a
--- /dev/null
+++ b/test/testcases/cplxdeps/orand.t
@@ -0,0 +1,87 @@
+feature complex_deps
+repo available 0 testtags <inline>
+#>=Pkg: A1 1 1 x86_64
+#>=Prv: A
+#>=Pkg: A2 1 1 x86_64
+#>=Prv: A
+#>=Pkg: B1 1 1 x86_64
+#>=Prv: B
+#>=Pkg: B2 1 1 x86_64
+#>=Prv: B
+#>=Pkg: C1 1 1 x86_64
+#>=Prv: C
+#>=Pkg: C2 1 1 x86_64
+#>=Prv: C
+#>=Pkg: D1 1 1 x86_64
+#>=Prv: D
+#>=Pkg: D2 1 1 x86_64
+#>=Prv: D
+#>=Pkg: X 1 1 x86_64
+#>=Req: (A | B) & (C | D)
+#>=Pkg: Y 1 1 x86_64
+#>=Con: (A | B) & (C | D)
+job install name X
+result rules <inline>
+#>rule job 3986285ed3e7fa05cb3367ca1e7f0d3d X-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 A1-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 A2-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 B1-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 B2-1-1.x86_64@available
+#>rule pkg 7d7fb2231997a6ba15d2c7c1d11d4ff1 -X-1-1.x86_64@available
+#>rule pkg cb5c72eeb44f643493f3df3e7e62f9dc C1-1-1.x86_64@available
+#>rule pkg cb5c72eeb44f643493f3df3e7e62f9dc C2-1-1.x86_64@available
+#>rule pkg cb5c72eeb44f643493f3df3e7e62f9dc D1-1-1.x86_64@available
+#>rule pkg cb5c72eeb44f643493f3df3e7e62f9dc D2-1-1.x86_64@available
+#>rule pkg cb5c72eeb44f643493f3df3e7e62f9dc -X-1-1.x86_64@available
+nextjob
+job install name Y
+result rules <inline>
+#>rule job 181d7955b2179c4ffdffedf0198f4807 Y-1-1.x86_64@available
+#>rule pkg 16cbba917580ca34f91961a74cfd07c2 -B1-1-1.x86_64@available
+#>rule pkg 16cbba917580ca34f91961a74cfd07c2 -D1-1-1.x86_64@available
+#>rule pkg 16cbba917580ca34f91961a74cfd07c2 -Y-1-1.x86_64@available
+#>rule pkg 1db9a5695f062c299dbb815adf4f2374 -A1-1-1.x86_64@available
+#>rule pkg 1db9a5695f062c299dbb815adf4f2374 -D2-1-1.x86_64@available
+#>rule pkg 1db9a5695f062c299dbb815adf4f2374 -Y-1-1.x86_64@available
+#>rule pkg 22f3f4d055f6daaeb6f5622907a9206f -A2-1-1.x86_64@available
+#>rule pkg 22f3f4d055f6daaeb6f5622907a9206f -D1-1-1.x86_64@available
+#>rule pkg 22f3f4d055f6daaeb6f5622907a9206f -Y-1-1.x86_64@available
+#>rule pkg 2823a39a3d1ae2f7d45ca97e97f5bf8e -A1-1-1.x86_64@available
+#>rule pkg 2823a39a3d1ae2f7d45ca97e97f5bf8e -C1-1-1.x86_64@available
+#>rule pkg 2823a39a3d1ae2f7d45ca97e97f5bf8e -Y-1-1.x86_64@available
+#>rule pkg 33a12cadfd9dd12dc60a3e250ae9f92a -B2-1-1.x86_64@available
+#>rule pkg 33a12cadfd9dd12dc60a3e250ae9f92a -C2-1-1.x86_64@available
+#>rule pkg 33a12cadfd9dd12dc60a3e250ae9f92a -Y-1-1.x86_64@available
+#>rule pkg 48a9e473b42b382f7cf46ac33e98ba76 -B2-1-1.x86_64@available
+#>rule pkg 48a9e473b42b382f7cf46ac33e98ba76 -C1-1-1.x86_64@available
+#>rule pkg 48a9e473b42b382f7cf46ac33e98ba76 -Y-1-1.x86_64@available
+#>rule pkg 714e9978244eb65bc57b7c4fac5a0430 -B1-1-1.x86_64@available
+#>rule pkg 714e9978244eb65bc57b7c4fac5a0430 -C1-1-1.x86_64@available
+#>rule pkg 714e9978244eb65bc57b7c4fac5a0430 -Y-1-1.x86_64@available
+#>rule pkg 86df5aaf92e5ea31f8efedf442fd431e -B1-1-1.x86_64@available
+#>rule pkg 86df5aaf92e5ea31f8efedf442fd431e -C2-1-1.x86_64@available
+#>rule pkg 86df5aaf92e5ea31f8efedf442fd431e -Y-1-1.x86_64@available
+#>rule pkg 87928b09a90963097188f62d00bfb3d9 -B2-1-1.x86_64@available
+#>rule pkg 87928b09a90963097188f62d00bfb3d9 -D1-1-1.x86_64@available
+#>rule pkg 87928b09a90963097188f62d00bfb3d9 -Y-1-1.x86_64@available
+#>rule pkg 92d66d3ad45eaa7d443a05245c9a0eaf -A2-1-1.x86_64@available
+#>rule pkg 92d66d3ad45eaa7d443a05245c9a0eaf -C1-1-1.x86_64@available
+#>rule pkg 92d66d3ad45eaa7d443a05245c9a0eaf -Y-1-1.x86_64@available
+#>rule pkg b5f410efacf9eb0b2b725e3e7b7d6e93 -B1-1-1.x86_64@available
+#>rule pkg b5f410efacf9eb0b2b725e3e7b7d6e93 -D2-1-1.x86_64@available
+#>rule pkg b5f410efacf9eb0b2b725e3e7b7d6e93 -Y-1-1.x86_64@available
+#>rule pkg c450fe9f8321047ee2cd1e6fc9f34df6 -A2-1-1.x86_64@available
+#>rule pkg c450fe9f8321047ee2cd1e6fc9f34df6 -C2-1-1.x86_64@available
+#>rule pkg c450fe9f8321047ee2cd1e6fc9f34df6 -Y-1-1.x86_64@available
+#>rule pkg da9eb4921698e87f788a89bd25cf75b8 -A1-1-1.x86_64@available
+#>rule pkg da9eb4921698e87f788a89bd25cf75b8 -C2-1-1.x86_64@available
+#>rule pkg da9eb4921698e87f788a89bd25cf75b8 -Y-1-1.x86_64@available
+#>rule pkg dfd799532ba714fd139acf879992c2de -A2-1-1.x86_64@available
+#>rule pkg dfd799532ba714fd139acf879992c2de -D2-1-1.x86_64@available
+#>rule pkg dfd799532ba714fd139acf879992c2de -Y-1-1.x86_64@available
+#>rule pkg eab097949c9719f1e7e196241c6ec0f4 -B2-1-1.x86_64@available
+#>rule pkg eab097949c9719f1e7e196241c6ec0f4 -D2-1-1.x86_64@available
+#>rule pkg eab097949c9719f1e7e196241c6ec0f4 -Y-1-1.x86_64@available
+#>rule pkg ede76598bf66f6be0b1fa3439c97a71b -A1-1-1.x86_64@available
+#>rule pkg ede76598bf66f6be0b1fa3439c97a71b -D1-1-1.x86_64@available
+#>rule pkg ede76598bf66f6be0b1fa3439c97a71b -Y-1-1.x86_64@available
diff --git a/test/testcases/recommendations/recommended_conflicts.t b/test/testcases/recommendations/recommended_conflicts.t
new file mode 100644
index 0000000..92afd75
--- /dev/null
+++ b/test/testcases/recommendations/recommended_conflicts.t
@@ -0,0 +1,16 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Rec: B
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Con: A
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>recommended B-2-1.noarch@available
diff --git a/test/testcases/recommendations/recommended_multirepo.t b/test/testcases/recommendations/recommended_multirepo.t
new file mode 100644
index 0000000..0addaf4
--- /dev/null
+++ b/test/testcases/recommendations/recommended_multirepo.t
@@ -0,0 +1,19 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Rec: B
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+repo other 0 testtags <inline>
+#>=Pkg: B 4 1 noarch
+#>=Pkg: B 6 1 noarch
+#>=Pkg: B 5 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>recommended B-6-1.noarch@other
diff --git a/test/testcases/recommendations/recommended_oldversion.t b/test/testcases/recommendations/recommended_oldversion.t
new file mode 100644
index 0000000..27c62f1
--- /dev/null
+++ b/test/testcases/recommendations/recommended_oldversion.t
@@ -0,0 +1,15 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Rec: B < 3
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>recommended B-2-1.noarch@available
diff --git a/test/testcases/recommendations/recommended_targeted.t b/test/testcases/recommendations/recommended_targeted.t
new file mode 100644
index 0000000..2b8a842
--- /dev/null
+++ b/test/testcases/recommendations/recommended_targeted.t
@@ -0,0 +1,15 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Rec: B = 2-1
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>recommended B-2-1.noarch@available
diff --git a/test/testcases/recommendations/recommended_version.t b/test/testcases/recommendations/recommended_version.t
new file mode 100644
index 0000000..b2e3637
--- /dev/null
+++ b/test/testcases/recommendations/recommended_version.t
@@ -0,0 +1,15 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Rec: B
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>recommended B-3-1.noarch@available
diff --git a/test/testcases/recommendations/suggested_conflicts.t b/test/testcases/recommendations/suggested_conflicts.t
new file mode 100644
index 0000000..8de6f3d
--- /dev/null
+++ b/test/testcases/recommendations/suggested_conflicts.t
@@ -0,0 +1,16 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Sug: B
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Con: A
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>suggested B-2-1.noarch@available
diff --git a/test/testcases/recommendations/suggested_multirepo.t b/test/testcases/recommendations/suggested_multirepo.t
new file mode 100644
index 0000000..c0a6d8f
--- /dev/null
+++ b/test/testcases/recommendations/suggested_multirepo.t
@@ -0,0 +1,19 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Sug: B
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+repo other 0 testtags <inline>
+#>=Pkg: B 4 1 noarch
+#>=Pkg: B 6 1 noarch
+#>=Pkg: B 5 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>suggested B-6-1.noarch@other
diff --git a/test/testcases/recommendations/suggested_oldversion.t b/test/testcases/recommendations/suggested_oldversion.t
new file mode 100644
index 0000000..b259b65
--- /dev/null
+++ b/test/testcases/recommendations/suggested_oldversion.t
@@ -0,0 +1,15 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Sug: B < 3
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>suggested B-2-1.noarch@available
diff --git a/test/testcases/recommendations/suggested_targeted.t b/test/testcases/recommendations/suggested_targeted.t
new file mode 100644
index 0000000..01da811
--- /dev/null
+++ b/test/testcases/recommendations/suggested_targeted.t
@@ -0,0 +1,15 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Sug: B = 2-1
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>suggested B-2-1.noarch@available
diff --git a/test/testcases/recommendations/suggested_version.t b/test/testcases/recommendations/suggested_version.t
new file mode 100644
index 0000000..1af6a77
--- /dev/null
+++ b/test/testcases/recommendations/suggested_version.t
@@ -0,0 +1,15 @@
+repo system 0 empty
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Sug: B
+#>=Pkg: B 1 1 noarch
+#>=Pkg: B 3 1 noarch
+#>=Pkg: B 2 1 noarch
+system i686 rpm system
+
+solverflags ignorerecommended
+job install name A
+
+result transaction,recommended,problems <inline>
+#>install A-1-1.noarch@available
+#>suggested B-3-1.noarch@available