Imported Upstream version 0.6.29 99/194199/1 upstream/0.6.29
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 30 Nov 2018 03:40:49 +0000 (12:40 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 30 Nov 2018 03:40:49 +0000 (12:40 +0900)
Change-Id: I9bac0213cb8a171344b94297e08c1c52595c0abe
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
89 files changed:
NEWS
TODO_1.0 [new file with mode: 0644]
VERSION.cmake
bindings/python/CMakeLists.txt
bindings/solv.i
doc/CMakeLists.txt
doc/Makefile.gen
doc/appdata2solv.txt
doc/archpkgs2solv.txt
doc/archrepo2solv.txt
doc/comps2solv.txt
doc/deb2solv.txt
doc/deltainfoxml2solv.txt
doc/dumpsolv.txt
doc/gen/appdata2solv.1 [moved from doc/appdata2solv.1 with 92% similarity]
doc/gen/archpkgs2solv.1 [moved from doc/archpkgs2solv.1 with 92% similarity]
doc/gen/archrepo2solv.1 [moved from doc/archrepo2solv.1 with 91% similarity]
doc/gen/comps2solv.1 [moved from doc/comps2solv.1 with 91% similarity]
doc/gen/deb2solv.1 [moved from doc/deb2solv.1 with 92% similarity]
doc/gen/deltainfoxml2solv.1 [moved from doc/deltainfoxml2solv.1 with 91% similarity]
doc/gen/dumpsolv.1 [moved from doc/dumpsolv.1 with 91% similarity]
doc/gen/helix2solv.1 [moved from doc/helix2solv.1 with 90% similarity]
doc/gen/installcheck.1 [moved from doc/installcheck.1 with 92% similarity]
doc/gen/libsolv-bindings.3 [moved from doc/libsolv-bindings.3 with 98% similarity]
doc/gen/libsolv-constantids.3 [moved from doc/libsolv-constantids.3 with 99% similarity]
doc/gen/libsolv-history.3 [moved from doc/libsolv-history.3 with 97% similarity]
doc/gen/libsolv-pool.3 [moved from doc/libsolv-pool.3 with 94% similarity]
doc/gen/libsolv.3 [moved from doc/libsolv.3 with 95% similarity]
doc/gen/mdk2solv.1 [moved from doc/mdk2solv.1 with 91% similarity]
doc/gen/mergesolv.1 [moved from doc/mergesolv.1 with 90% similarity]
doc/gen/repomdxml2solv.1 [moved from doc/repomdxml2solv.1 with 92% similarity]
doc/gen/rpmdb2solv.1 [moved from doc/rpmdb2solv.1 with 94% similarity]
doc/gen/rpmmd2solv.1 [moved from doc/rpmmd2solv.1 with 91% similarity]
doc/gen/rpms2solv.1 [moved from doc/rpms2solv.1 with 93% similarity]
doc/gen/susetags2solv.1 [moved from doc/susetags2solv.1 with 92% similarity]
doc/gen/testsolv.1 [moved from doc/testsolv.1 with 93% similarity]
doc/gen/updateinfoxml2solv.1 [moved from doc/updateinfoxml2solv.1 with 90% similarity]
doc/helix2solv.txt
doc/installcheck.txt
doc/libsolv-bindings.txt
doc/libsolv-constantids.txt
doc/libsolv-history.txt
doc/libsolv-pool.txt
doc/libsolv.txt
doc/mdk2solv.txt
doc/mergesolv.txt
doc/repomdxml2solv.txt
doc/rpmdb2solv.txt
doc/rpmmd2solv.txt
doc/rpms2solv.txt
doc/susetags2solv.txt
doc/testsolv.txt
doc/updateinfoxml2solv.txt
examples/solv/deltarpm.c
examples/solv/repoinfo.c
examples/solv/repoinfo_config_yum.c
examples/solv/repoinfo_download.c
examples/solv/solv.c
ext/pool_parserpmrichdep.c
ext/repo_rpmdb.c
ext/repo_susetags.c
ext/testcase.c
package/libsolv.changes
src/cplxdeps.c
src/cplxdeps.h
src/policy.c
src/pool.c
src/pool.h
src/poolid.c
src/rules.c
src/selection.c
src/solver.c
src/solver_private.h
test/testcases/cplxdeps/and.t [new file with mode: 0644]
test/testcases/cplxdeps/andor.t [new file with mode: 0644]
test/testcases/cplxdeps/if.t [new file with mode: 0644]
test/testcases/cplxdeps/ifelse.t [new file with mode: 0644]
test/testcases/cplxdeps/or.t [new file with mode: 0644]
test/testcases/cplxdeps/orand.t [new file with mode: 0644]
test/testcases/recommendations/recommended_conflicts.t [new file with mode: 0644]
test/testcases/recommendations/recommended_multirepo.t [new file with mode: 0644]
test/testcases/recommendations/recommended_oldversion.t [new file with mode: 0644]
test/testcases/recommendations/recommended_targeted.t [new file with mode: 0644]
test/testcases/recommendations/recommended_version.t [new file with mode: 0644]
test/testcases/recommendations/suggested_conflicts.t [new file with mode: 0644]
test/testcases/recommendations/suggested_multirepo.t [new file with mode: 0644]
test/testcases/recommendations/suggested_oldversion.t [new file with mode: 0644]
test/testcases/recommendations/suggested_targeted.t [new file with mode: 0644]
test/testcases/recommendations/suggested_version.t [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index b3fd37b..396bfdb 100644 (file)
--- 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 (file)
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:
+
index f4958cb..f24ed63 100644 (file)
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "0")
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "6")
-SET(LIBSOLV_PATCH "28")
+SET(LIBSOLV_PATCH "29")
 
index a83695f..64ef528 100644 (file)
@@ -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)
 
index 354cde7..6313d9b 100644 (file)
@@ -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 {
index 13e086c..b18596d 100644 (file)
@@ -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")
index 84a1095..2e8c4a1 100644 (file)
@@ -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 $<
index 3ccb4b5..c31311a 100644 (file)
@@ -37,3 +37,7 @@ mergesolv(1)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 2a17066..4ce3155 100644 (file)
@@ -33,3 +33,7 @@ pacman(8)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 3f5b138..1a7791c 100644 (file)
@@ -29,3 +29,7 @@ pacman(8)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 23e304e..8d98708 100644 (file)
@@ -27,3 +27,7 @@ mergesolv(1), createrepo(8)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 0907383..cb42ff7 100644 (file)
@@ -33,3 +33,7 @@ deb(5), dpkg-deb(1)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index f14a843..13c987d 100644 (file)
@@ -27,3 +27,7 @@ mergesolv(1), createrepo(8)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index ec2d771..b09aa97 100644 (file)
@@ -24,3 +24,7 @@ Write the contents in JSON format.
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
similarity index 92%
rename from doc/appdata2solv.1
rename to doc/gen/appdata2solv.1
index b5fdf9f..4fe217d 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 92%
rename from doc/archpkgs2solv.1
rename to doc/gen/archpkgs2solv.1
index 6052aee..bb47364 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 91%
rename from doc/archrepo2solv.1
rename to doc/gen/archrepo2solv.1
index 94f5c41..9d7c868 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 91%
rename from doc/comps2solv.1
rename to doc/gen/comps2solv.1
index c6f8d32..2be0bc9 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 92%
rename from doc/deb2solv.1
rename to doc/gen/deb2solv.1
index 95f5091..7da3828 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 91%
rename from doc/deltainfoxml2solv.1
rename to doc/gen/deltainfoxml2solv.1
index 11cda74..0ef0bb4 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 91%
rename from doc/dumpsolv.1
rename to doc/gen/dumpsolv.1
index cb6a136..eed45fe 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 90%
rename from doc/helix2solv.1
rename to doc/gen/helix2solv.1
index 07d9497..dacc5fe 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 92%
rename from doc/installcheck.1
rename to doc/gen/installcheck.1
index 7ee3e4d..7965f00 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 98%
rename from doc/libsolv-bindings.3
rename to doc/gen/libsolv-bindings.3
index f2d8e8d..7350224 100644 (file)
@@ -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
similarity index 99%
rename from doc/libsolv-constantids.3
rename to doc/gen/libsolv-constantids.3
index 327150c..87a14e6 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 97%
rename from doc/libsolv-history.3
rename to doc/gen/libsolv-history.3
index 872cd4e..6a600ac 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 94%
rename from doc/libsolv-pool.3
rename to doc/gen/libsolv-pool.3
index adc13e3..d324f68 100644 (file)
@@ -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\&.
similarity index 95%
rename from doc/libsolv.3
rename to doc/gen/libsolv.3
index 24ab788..dcebb02 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 91%
rename from doc/mdk2solv.1
rename to doc/gen/mdk2solv.1
index 4400c9b..513187a 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 90%
rename from doc/mergesolv.1
rename to doc/gen/mergesolv.1
index 3ff00e8..1c706c7 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 92%
rename from doc/repomdxml2solv.1
rename to doc/gen/repomdxml2solv.1
index e14b974..aeac7bd 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 94%
rename from doc/rpmdb2solv.1
rename to doc/gen/rpmdb2solv.1
index 2b4b931..79c6d26 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 91%
rename from doc/rpmmd2solv.1
rename to doc/gen/rpmmd2solv.1
index 2d8e245..44ea70f 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 93%
rename from doc/rpms2solv.1
rename to doc/gen/rpms2solv.1
index e67c6ef..11b3671 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 92%
rename from doc/susetags2solv.1
rename to doc/gen/susetags2solv.1
index 9b07094..43a616a 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 93%
rename from doc/testsolv.1
rename to doc/gen/testsolv.1
index 0e71874..158aedc 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
similarity index 90%
rename from doc/updateinfoxml2solv.1
rename to doc/gen/updateinfoxml2solv.1
index 20ab3ad..cd0386d 100644 (file)
@@ -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
 .\" -----------------------------------------------------------------
index f9b303f..40d523a 100644 (file)
@@ -22,3 +22,7 @@ input and writes it in solv file format to standard output.
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 99eb279..5780772 100644 (file)
@@ -27,3 +27,7 @@ file.
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 4de090f..83ae6c2 100644 (file)
@@ -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
+////
index e067642..907a7e5 100644 (file)
@@ -678,3 +678,6 @@ Author
 ------
 Michael Schroeder <mls@suse.de>
 
+////
+vim: syntax=asciidoc
+////
index da59fe5..d0a5e62 100644 (file)
@@ -111,3 +111,7 @@ were removed in February.
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 69291a4..cc7707a 100644 (file)
@@ -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
+////
index af44168..f101808 100644 (file)
@@ -56,3 +56,6 @@ Author
 ------
 Michael Schroeder <mls@suse.de>
 
+////
+vim: syntax=asciidoc
+////
index 2616a87..eb2ac14 100644 (file)
@@ -31,3 +31,7 @@ genhdlist2(1)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index bbe8c72..8ae67d1 100644 (file)
@@ -23,3 +23,7 @@ Autoexpand SUSE pattern and product provides into packages.
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index feb859c..3b77820 100644 (file)
@@ -34,3 +34,7 @@ rpmmd2solv(1), mergesolv(1), createrepo(8)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 0c4585f..ad8314f 100644 (file)
@@ -57,3 +57,7 @@ rpms2solv(1)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index c72ccc9..f103f06 100644 (file)
@@ -28,3 +28,7 @@ repomdxml2solv(1), mergesolv(1), createrepo(8)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 244dffb..11bdcf0 100644 (file)
@@ -46,3 +46,7 @@ rpmdb2solv(1)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 9a2e2f1..0d61c4d 100644 (file)
@@ -37,3 +37,7 @@ Autoexpand SUSE pattern and product provides into packages.
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index dc3a34e..eb52d95 100644 (file)
@@ -39,3 +39,7 @@ to encountered problems.
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 7e7c5fc..6ebdeb4 100644 (file)
@@ -25,3 +25,7 @@ mergesolv(1), createrepo(8)
 Author
 ------
 Michael Schroeder <mls@suse.de>
+
+////
+vim: syntax=asciidoc
+////
index 551d570..438c2d8 100644 (file)
@@ -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);
index 91f7c28..6273972 100644 (file)
 #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)
index 6e2e66a..efccf1e 100644 (file)
@@ -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;
index 5ba3014..f5ba8b9 100644 (file)
@@ -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);
index 3301126..615c83d 100644 (file)
@@ -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)
index d3e559e..93d77f8 100644 (file)
@@ -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;
index b98720a..9fb5a29 100644 (file)
@@ -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;
index 41c7a78..52d5e5e 100644 (file)
@@ -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);
index 26acefa..77cc719 100644 (file)
@@ -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 }
 };
index 5418084..21bdbd1 100644 (file)
@@ -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
index aadbc48..6c40752 100644 (file)
@@ -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))
index 798b485..7c5946a 100644 (file)
@@ -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
 
index a6d3441..468be67 100644 (file)
@@ -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);
index bd97026..b596ace 100644 (file)
@@ -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))
                {
index 3eeea06..f6a5493 100644 (file)
@@ -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)
 
index 3a8a3c8..bb8d4f6 100644 (file)
@@ -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);
index 26b93ea..5654330 100644 (file)
@@ -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;
index 37c6184..16fe3a7 100644 (file)
@@ -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;
        }
index bec1d9f..5d1052d 100644 (file)
@@ -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);
index fe80881..a234223 100644 (file)
@@ -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 (file)
index 0000000..d4ef47e
--- /dev/null
@@ -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 (file)
index 0000000..f60745d
--- /dev/null
@@ -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 (file)
index 0000000..7e3dead
--- /dev/null
@@ -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 (file)
index 0000000..ef5bab9
--- /dev/null
@@ -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 (file)
index 0000000..7446799
--- /dev/null
@@ -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 (file)
index 0000000..8a5108a
--- /dev/null
@@ -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 (file)
index 0000000..92afd75
--- /dev/null
@@ -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 (file)
index 0000000..0addaf4
--- /dev/null
@@ -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 (file)
index 0000000..27c62f1
--- /dev/null
@@ -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 (file)
index 0000000..2b8a842
--- /dev/null
@@ -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 (file)
index 0000000..b2e3637
--- /dev/null
@@ -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 (file)
index 0000000..8de6f3d
--- /dev/null
@@ -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 (file)
index 0000000..c0a6d8f
--- /dev/null
@@ -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 (file)
index 0000000..b259b65
--- /dev/null
@@ -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 (file)
index 0000000..01da811
--- /dev/null
@@ -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 (file)
index 0000000..1af6a77
--- /dev/null
@@ -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