summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS12
-rw-r--r--VERSION.cmake2
-rw-r--r--bindings/solv.i4
-rw-r--r--doc/gen/libsolv-bindings.34
-rw-r--r--doc/gen/libsolv-pool.34
-rw-r--r--doc/gen/rpmdb2solv.116
-rw-r--r--doc/rpmdb2solv.txt3
-rw-r--r--ext/repo_comps.c37
-rw-r--r--ext/repo_rpmdb.c2
-rw-r--r--ext/repo_rpmdb_bdb.h1
-rw-r--r--ext/repo_rpmdb_librpm.h31
-rw-r--r--ext/repo_updateinfoxml.c38
-rw-r--r--ext/testcase.c21
-rw-r--r--package/libsolv.changes13
-rw-r--r--src/knownid.h4
-rw-r--r--src/repo_write.c26
-rw-r--r--src/rules.c39
-rw-r--r--test/testcases/choicerules/choice3.t17
-rw-r--r--test/testcases/choicerules/choice4.t31
-rw-r--r--tools/rpmdb2solv.c26
20 files changed, 298 insertions, 33 deletions
diff --git a/NEWS b/NEWS
index ca6efa9..7e91d66 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,18 @@
This file contains the major changes between
libsolv versions:
+Version 0.7.17
+- selected bug fixes:
+ * repo_write: fix handling of nested flexarray
+ * improve choicerule generation a bit more to cover more cases
+ * harden testcase parser against repos being added too late
+ * support python-3.10
+ * check %_dbpath macro in rpmdb code
+- new features:
+ * handle default/visible/langonly attributes in comps parser
+ * support multiple collections in updateinfo parser
+ * add '-D' option in rpmdb2solv to set the dbpath
+
Version 0.7.16
- selected bug fixes:
* do not ask the namespace callback for splitprovides when writing
diff --git a/VERSION.cmake b/VERSION.cmake
index c218401..adf18d2 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "1")
SET(LIBSOLV_MAJOR "0")
SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "16")
+SET(LIBSOLV_PATCH "17")
diff --git a/bindings/solv.i b/bindings/solv.i
index 48d3f1f..1882b13 100644
--- a/bindings/solv.i
+++ b/bindings/solv.i
@@ -44,7 +44,11 @@ typedef struct {
#if defined(SWIGPYTHON)
const void *pybuf = 0;
Py_ssize_t pysize = 0;
+%#if PY_VERSION_HEX >= 0x03000000
+ res = PyBytes_AsStringAndSize($input, (char **)&pybuf, &pysize);
+%#else
res = PyObject_AsReadBuffer($input, &pybuf, &pysize);
+%#endif
if (res < 0) {
%argument_fail(res, "BinaryBlob", $symname, $argnum);
} else {
diff --git a/doc/gen/libsolv-bindings.3 b/doc/gen/libsolv-bindings.3
index 8e6417e..7384d2a 100644
--- a/doc/gen/libsolv-bindings.3
+++ b/doc/gen/libsolv-bindings.3
@@ -2,12 +2,12 @@
.\" Title: Libsolv-Bindings
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\" Date: 01/21/2020
+.\" Date: 11/18/2020
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-BINDINGS" "3" "01/21/2020" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-BINDINGS" "3" "11/18/2020" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/gen/libsolv-pool.3 b/doc/gen/libsolv-pool.3
index 6d94939..ab1b3f0 100644
--- a/doc/gen/libsolv-pool.3
+++ b/doc/gen/libsolv-pool.3
@@ -2,12 +2,12 @@
.\" Title: Libsolv-Pool
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\" Date: 01/21/2020
+.\" Date: 11/18/2020
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-POOL" "3" "01/21/2020" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-POOL" "3" "11/18/2020" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
diff --git a/doc/gen/rpmdb2solv.1 b/doc/gen/rpmdb2solv.1
index 6f84a7f..c54c319 100644
--- a/doc/gen/rpmdb2solv.1
+++ b/doc/gen/rpmdb2solv.1
@@ -2,12 +2,12 @@
.\" Title: rpmdb2solv
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\" Date: 09/14/2018
+.\" Date: 11/18/2020
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "RPMDB2SOLV" "1" "09/14/2018" "libsolv" "LIBSOLV"
+.TH "RPMDB2SOLV" "1" "11/18/2020" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -55,6 +55,13 @@ Use
as root directory\&.
.RE
.PP
+\fB\-D\fR \fIDBPATH\fR
+.RS 4
+Use the database in the
+\fIDBPATH\fR
+directory\&.
+.RE
+.PP
\fB\-k\fR
.RS 4
Read pubkeys from the rpm database instead of installed packages\&. Note that many distributions stopped storing pubkeys in the database but use a directory like
@@ -83,6 +90,11 @@ Do not read any packages from the rpm database\&. This is useful together with
to only convert SUSE products\&.
.RE
.PP
+\fB\-C\fR
+.RS 4
+Include the package changelog in the generated solv file\&.
+.RE
+.PP
\fB\-X\fR
.RS 4
Autoexpand SUSE pattern and product provides into packages\&.
diff --git a/doc/rpmdb2solv.txt b/doc/rpmdb2solv.txt
index 128e179..8e31cb8 100644
--- a/doc/rpmdb2solv.txt
+++ b/doc/rpmdb2solv.txt
@@ -29,6 +29,9 @@ format is like rpm's --percent option.
*-r* 'ROOTDIR'::
Use 'ROOTDIR' as root directory.
+*-D* 'DBPATH'::
+Use the database in the 'DBPATH' directory.
+
*-k*::
Read pubkeys from the rpm database instead of installed packages.
Note that many distributions stopped storing pubkeys in the
diff --git a/ext/repo_comps.c b/ext/repo_comps.c
index 6991656..014f89a 100644
--- a/ext/repo_comps.c
+++ b/ext/repo_comps.c
@@ -29,7 +29,6 @@
* TODO:
*
* what's the difference between group/category?
- * handle "default" and "langonly".
*
* maybe handle REL_COND in solver recommends handling?
*/
@@ -97,10 +96,26 @@ struct parsedata {
Solvable *solvable;
const char *kind;
+ int isdefault;
+ int isvisible;
Id handle;
};
+#define COMPS_DEFAULT_ISVISIBLE 1
+#define COMPS_DEFAULT_ISDEFAULT 0
+
+/* Return true if "true", false if "false", default_value otherwise */
+static int
+parse_boolean(char *content, int default_value)
+{
+ if (!strcmp(content, "true"))
+ return 1;
+ if (!strcmp(content, "false"))
+ return 0;
+ return default_value;
+}
+
static void
startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
@@ -116,6 +131,8 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
pd->handle = s - pool->solvables;
pd->kind = state == STATE_GROUP ? "group" : "category";
+ pd->isvisible = COMPS_DEFAULT_ISVISIBLE;
+ pd->isdefault = COMPS_DEFAULT_ISDEFAULT;
break;
case STATE_NAME:
@@ -166,6 +183,10 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
s->evr = ID_EMPTY;
if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0);
+ if (pd->isvisible)
+ repodata_set_void(pd->data, pd->handle, SOLVABLE_ISVISIBLE);
+ if (pd->isdefault)
+ repodata_set_void(pd->data, pd->handle, SOLVABLE_ISDEFAULT);
pd->solvable = 0;
break;
@@ -194,7 +215,19 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
break;
case STATE_USERVISIBLE:
- repodata_set_void(pd->data, pd->handle, SOLVABLE_ISVISIBLE);
+ pd->isvisible = parse_boolean(content, COMPS_DEFAULT_ISVISIBLE);
+ break;
+
+ case STATE_DEFAULT:
+ pd->isdefault = parse_boolean(content, COMPS_DEFAULT_ISDEFAULT);
+ break;
+
+ case STATE_LANG_ONLY:
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_LANGONLY, content);
+ break;
+
+ case STATE_LANGONLY:
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_LANGONLY, content);
break;
case STATE_DISPLAY_ORDER:
diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c
index 67ce81d..d78893e 100644
--- a/ext/repo_rpmdb.c
+++ b/ext/repo_rpmdb.c
@@ -1349,6 +1349,8 @@ freestate(struct rpmdbstate *state)
#ifdef ENABLE_RPMDB
if (state->dbenvopened)
closedbenv(state);
+ if (state->dbpath_allocated)
+ solv_free((char *)state->dbpath);
#endif
if (state->rootdir)
solv_free(state->rootdir);
diff --git a/ext/repo_rpmdb_bdb.h b/ext/repo_rpmdb_bdb.h
index 1c83317..4043ef1 100644
--- a/ext/repo_rpmdb_bdb.h
+++ b/ext/repo_rpmdb_bdb.h
@@ -48,6 +48,7 @@ struct rpmdbstate {
int dbenvopened; /* database environment opened */
int pkgdbopened; /* package database openend */
const char *dbpath; /* path to the database */
+ int dbpath_allocated; /* do we need to free the path? */
DB_ENV *dbenv; /* database environment */
DB *db; /* packages database */
diff --git a/ext/repo_rpmdb_librpm.h b/ext/repo_rpmdb_librpm.h
index 35a46fa..3f9798c 100644
--- a/ext/repo_rpmdb_librpm.h
+++ b/ext/repo_rpmdb_librpm.h
@@ -12,6 +12,7 @@
*
*/
+#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmmacro.h>
@@ -24,6 +25,7 @@ struct rpmdbstate {
int dbenvopened; /* database environment opened */
const char *dbpath; /* path to the database */
+ int dbpath_allocated; /* do we need to free the path? */
rpmts ts;
rpmdbMatchIterator mi; /* iterator over packages database */
@@ -45,6 +47,13 @@ access_rootdir(struct rpmdbstate *state, const char *dir, int mode)
static void
detect_dbpath(struct rpmdbstate *state)
{
+ state->dbpath = rpmExpand("%{?_dbpath}", NULL);
+ if (state->dbpath && *state->dbpath)
+ {
+ state->dbpath_allocated = 1;
+ return;
+ }
+ solv_free((char *)state->dbpath);
state->dbpath = access_rootdir(state, "/var/lib/rpm", W_OK) == -1
&& (access_rootdir(state, "/usr/share/rpm/Packages", R_OK) == 0 || access_rootdir(state, "/usr/share/rpm/rpmdb.sqlite", R_OK) == 0)
? "/usr/share/rpm" : "/var/lib/rpm";
@@ -90,6 +99,24 @@ stat_database(struct rpmdbstate *state, struct stat *statbuf)
return 0;
}
+/* rpm-4.16.0 cannot read the database if _db_backend is not set */
+#ifndef HAVE_RPMDBNEXTITERATORHEADERBLOB
+static void
+set_db_backend()
+{
+ static int db_backend_set;
+ char *db_backend;
+
+ if (db_backend_set)
+ return;
+ db_backend_set = 1;
+ db_backend = rpmExpand("%{?_db_backend}", NULL);
+ if (!db_backend || !*db_backend)
+ rpmReadConfigFiles(NULL, NULL);
+ solv_free(db_backend);
+}
+#endif
+
static int
opendbenv(struct rpmdbstate *state)
{
@@ -108,6 +135,10 @@ opendbenv(struct rpmdbstate *state)
delMacro(NULL, "_dbpath");
return 0;
}
+#ifndef HAVE_RPMDBNEXTITERATORHEADERBLOB
+ if (!strcmp(RPMVERSION, "4.16.0"))
+ set_db_backend();
+#endif
if (rpmtsOpenDB(ts, O_RDONLY))
{
pool_error(state->pool, 0, "rpmtsOpenDB failed: %s", strerror(errno));
diff --git a/ext/repo_updateinfoxml.c b/ext/repo_updateinfoxml.c
index 36d76b5..22f7093 100644
--- a/ext/repo_updateinfoxml.c
+++ b/ext/repo_updateinfoxml.c
@@ -110,9 +110,10 @@ struct parsedata {
Id handle;
Solvable *solvable;
time_t buildtime;
- Id collhandle;
+ Id pkghandle;
struct solv_xmlparser xmlp;
struct joindata jd;
+ Id collhandle;
};
/*
@@ -287,6 +288,12 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
}
break;
+ case STATE_COLLECTION:
+ {
+ pd->collhandle = repodata_new_handle(pd->data);
+ }
+ break;
+
/* <package arch="ppc64" name="imlib-debuginfo" release="6.fc8"
* src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm"
* version="1.9.15">
@@ -326,12 +333,12 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, id, 0);
}
- /* who needs the collection anyway? */
- pd->collhandle = repodata_new_handle(pd->data);
- repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_NAME, n);
- repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_EVR, evr);
+ /* UPDATE_COLLECTION is misnamed, it should have been UPDATE_PACKAGE */
+ pd->pkghandle = repodata_new_handle(pd->data);
+ repodata_set_id(pd->data, pd->pkghandle, UPDATE_COLLECTION_NAME, n);
+ repodata_set_id(pd->data, pd->pkghandle, UPDATE_COLLECTION_EVR, evr);
if (a)
- repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_ARCH, a);
+ repodata_set_id(pd->data, pd->pkghandle, UPDATE_COLLECTION_ARCH, a);
break;
}
case STATE_MODULE:
@@ -364,6 +371,7 @@ startElement(struct solv_xmlparser *xmlp, int state, const char *name, const cha
if (arch)
repodata_set_poolstr(pd->data, module_handle, UPDATE_MODULE_ARCH, arch);
repodata_add_flexarray(pd->data, pd->handle, UPDATE_MODULE, module_handle);
+ repodata_add_flexarray(pd->data, pd->collhandle, UPDATE_MODULE, module_handle);
break;
}
@@ -427,15 +435,21 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
repodata_set_str(pd->data, pd->handle, UPDATE_MESSAGE, content);
break;
- case STATE_PACKAGE:
- repodata_add_flexarray(pd->data, pd->handle, UPDATE_COLLECTION, pd->collhandle);
+ case STATE_COLLECTION:
+ repodata_add_flexarray(pd->data, pd->handle, UPDATE_COLLECTIONLIST, pd->collhandle);
pd->collhandle = 0;
break;
+ case STATE_PACKAGE:
+ repodata_add_flexarray(pd->data, pd->handle, UPDATE_COLLECTION, pd->pkghandle);
+ repodata_add_flexarray(pd->data, pd->collhandle, UPDATE_COLLECTION, pd->pkghandle);
+ pd->pkghandle = 0;
+ break;
+
/* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
/* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
case STATE_FILENAME:
- repodata_set_str(pd->data, pd->collhandle, UPDATE_COLLECTION_FILENAME, content);
+ repodata_set_str(pd->data, pd->pkghandle, UPDATE_COLLECTION_FILENAME, content);
break;
/* <reboot_suggested>True</reboot_suggested> */
@@ -444,7 +458,7 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
/* FIXME: this is per-package, the global flag should be computed at runtime */
repodata_set_void(pd->data, pd->handle, UPDATE_REBOOT);
- repodata_set_void(pd->data, pd->collhandle, UPDATE_REBOOT);
+ repodata_set_void(pd->data, pd->pkghandle, UPDATE_REBOOT);
}
break;
@@ -454,7 +468,7 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
/* FIXME: this is per-package, the global flag should be computed at runtime */
repodata_set_void(pd->data, pd->handle, UPDATE_RESTART);
- repodata_set_void(pd->data, pd->collhandle, UPDATE_RESTART);
+ repodata_set_void(pd->data, pd->pkghandle, UPDATE_RESTART);
}
break;
@@ -464,7 +478,7 @@ endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
/* FIXME: this is per-package, the global flag should be computed at runtime */
repodata_set_void(pd->data, pd->handle, UPDATE_RELOGIN);
- repodata_set_void(pd->data, pd->collhandle, UPDATE_RELOGIN);
+ repodata_set_void(pd->data, pd->pkghandle, UPDATE_RELOGIN);
}
break;
default:
diff --git a/ext/testcase.c b/ext/testcase.c
index 0be7a21..8fb6d79 100644
--- a/ext/testcase.c
+++ b/ext/testcase.c
@@ -1991,6 +1991,7 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
Id *genid = 0;
int ngenid = 0;
Queue autoinstq;
+ int oldjobsize = job ? job->count : 0;
if (resultp)
*resultp = 0;
@@ -2065,6 +2066,21 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
int prio, subprio;
const char *rdata;
+ if (pool->considered)
+ {
+ pool_error(pool, 0, "testcase_read: cannot add repos after packages were disabled");
+ continue;
+ }
+ if (solv)
+ {
+ pool_error(pool, 0, "testcase_read: cannot add repos after the solver was created");
+ continue;
+ }
+ if (job && job->count != oldjobsize)
+ {
+ pool_error(pool, 0, "testcase_read: cannot add repos after jobs have been created");
+ continue;
+ }
prepared = 0;
if (!poolflagsreset)
{
@@ -2125,6 +2141,11 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
int i;
/* must set the disttype before the arch */
+ if (job && job->count != oldjobsize)
+ {
+ pool_error(pool, 0, "testcase_read: cannot change the system after jobs have been created");
+ continue;
+ }
prepared = 0;
if (strcmp(pieces[2], "*") != 0)
{
diff --git a/package/libsolv.changes b/package/libsolv.changes
index 2f4bfe3..d477d71 100644
--- a/package/libsolv.changes
+++ b/package/libsolv.changes
@@ -1,4 +1,17 @@
-------------------------------------------------------------------
+Tue Jan 19 15:09:12 CET 2021 - mls@suse.de
+
+- repo_write: fix handling of nested flexarray
+- improve choicerule generation a bit more to cover more cases
+- harden testcase parser against repos being added too late
+- support python-3.10
+- check %_dbpath macro in rpmdb code
+- handle default/visible/langonly attributes in comps parser
+- support multiple collections in updateinfo parser
+- add '-D' option in rpmdb2solv to set the dbpath
+- bump version to 0.7.17
+
+-------------------------------------------------------------------
Tue Oct 20 12:04:00 CEST 2020 - mls@suse.de
- do not ask the namespace callback for splitprovides when writing
diff --git a/src/knownid.h b/src/knownid.h
index 4c1730b..d131e78 100644
--- a/src/knownid.h
+++ b/src/knownid.h
@@ -267,6 +267,10 @@ KNOWNID(LIBSOLV_SELF_DESTRUCT_PKG, "libsolv-self-destruct-pkg()"), /* this
KNOWNID(SOLVABLE_CONSTRAINS, "solvable:constrains"), /* conda */
KNOWNID(SOLVABLE_TRACK_FEATURES, "solvable:track_features"), /* conda */
+KNOWNID(SOLVABLE_ISDEFAULT, "solvable:isdefault"),
+KNOWNID(SOLVABLE_LANGONLY, "solvable:langonly"),
+
+KNOWNID(UPDATE_COLLECTIONLIST, "update:collectionlist"), /* list of UPDATE_COLLECTION (actually packages) and UPDATE_MODULE */
KNOWNID(ID_NUM_INTERNAL, 0)
diff --git a/src/repo_write.c b/src/repo_write.c
index 2a03e58..0f9fc4f 100644
--- a/src/repo_write.c
+++ b/src/repo_write.c
@@ -570,25 +570,29 @@ collect_needed_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyV
break;
case REPOKEY_TYPE_FIXARRAY:
case REPOKEY_TYPE_FLEXARRAY:
- if (kv->entry == 0)
+ if (kv->entry)
{
- if (kv->eof != 2)
- *cbdata->sp++ = 0; /* mark start */
- }
- else
- {
- /* just finished a schema, rewind to start */
+ /* finish schema, rewind to start */
Id *sp = cbdata->sp - 1;
*sp = 0;
while (sp[-1])
sp--;
- if (kv->entry == 1 || key->type == REPOKEY_TYPE_FLEXARRAY)
+ if (sp[-2] >= 0)
+ cbdata->subschemata[sp[-2]] = repodata_schema2id(cbdata->target, sp, 1);
+ cbdata->sp = sp - 2;
+ }
+ if (kv->eof != 2)
+ {
+ /* start new schema */
+ if (kv->entry == 0 || key->type == REPOKEY_TYPE_FLEXARRAY)
{
cbdata->subschemata = solv_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
- cbdata->subschemata[cbdata->nsubschemata++] = repodata_schema2id(cbdata->target, sp, 1);
+ *cbdata->sp++ = cbdata->nsubschemata++;
}
- cbdata->sp = kv->eof == 2 ? sp - 1: sp;
- }
+ else
+ *cbdata->sp++ = -1;
+ *cbdata->sp++ = 0;
+ }
break;
default:
break;
diff --git a/src/rules.c b/src/rules.c
index 6c8e82b..b3609bb 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -3225,6 +3225,40 @@ solver_choicerulecheck2(Solver *solv, Id pi, Id pt, Queue *q)
return 0; /* not newest */
}
+static int
+solver_choicerulecheck3(Solver *solv, Id pt, Queue *q)
+{
+ Pool *pool = solv->pool;
+ Id p, pp;
+ int i;
+
+ if (!q->count || q->elements[0] != pt)
+ {
+ Solvable *s = pool->solvables + pt;
+ if (q->count)
+ queue_empty(q);
+ /* no installed package, so check all with same name */
+ queue_push2(q, pt, 0);
+ FOR_PROVIDES(p, pp, s->name)
+ if (pool->solvables[p].name == s->name && p != pt)
+ queue_push(q, p);
+ queue_push(q, pt);
+ }
+ if (q->count <= 3)
+ return q->count == 3 && q->elements[2] == pt ? 1 : 0;
+ if (!q->elements[1])
+ {
+ queue_deleten(q, 0, 2);
+ policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE);
+ queue_unshift(q, 1); /* filter mark */
+ queue_unshift(q, pt);
+ }
+ for (i = 2; i < q->count; i++)
+ if (q->elements[i] == pt)
+ return 1;
+ return 0; /* not newest */
+}
+
static inline void
queue_removeelement(Queue *q, Id el)
{
@@ -3381,6 +3415,11 @@ solver_addchoicerules(Solver *solv)
isnewest = 0;
break;
}
+ if (!p2 && !solver_choicerulecheck3(solv, -p, &qcheck2))
+ {
+ isnewest = 0;
+ break;
+ }
}
/* do extra checking */
for (i = j = 0; i < qi.count; i += 2)
diff --git a/test/testcases/choicerules/choice3.t b/test/testcases/choicerules/choice3.t
new file mode 100644
index 0000000..d5d41ac
--- /dev/null
+++ b/test/testcases/choicerules/choice3.t
@@ -0,0 +1,17 @@
+repo system 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Prv: libA
+#>=Pkg: B 1 1 noarch
+#>=Req: libA
+repo available 0 testtags <inline>
+#>=Pkg: B 1 1 noarch
+#>=Req: libA
+#>=Pkg: A 2 1 noarch
+#>=Pkg: Anew 2 1 noarch
+#>=Prv: libA
+system i686 rpm system
+
+job update all packages
+result transaction,problems <inline>
+#>install Anew-2-1.noarch@available
+#>upgrade A-1-1.noarch@system A-2-1.noarch@available
diff --git a/test/testcases/choicerules/choice4.t b/test/testcases/choicerules/choice4.t
new file mode 100644
index 0000000..1bf9f48
--- /dev/null
+++ b/test/testcases/choicerules/choice4.t
@@ -0,0 +1,31 @@
+repo system 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Prv: libA = 1-1
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Prv: libA = 1-1
+#>=Pkg: Anew 1 1 noarch
+#>=Prv: libA = 1-1
+#>=Pkg: B 1 1 noarch
+#>=Req: libA = 1-1
+#>=Pkg: A 2 1 noarch
+#>=Prv: libA = 2-1
+#>=Pkg: Anew 2 1 noarch
+#>=Prv: libA = 2-1
+#>=Pkg: B 2 1 noarch
+#>=Req: libA = 2-1
+#>=Pkg: A 2 2 noarch
+#>=Prv: libA = 2-2
+#>=Pkg: Anew 2 2 noarch
+#>=Prv: libA = 2-2
+#>=Pkg: B 2 2 noarch
+#>=Req: libA = 2-2
+#>=Pkg: C 2 1 noarch
+#>=Req: B = 2
+system i686 rpm system
+
+job install name C
+result transaction,problems <inline>
+#>install B-2-2.noarch@available
+#>install C-2-1.noarch@available
+#>upgrade A-1-1.noarch@system A-2-2.noarch@available
diff --git a/tools/rpmdb2solv.c b/tools/rpmdb2solv.c
index 1a04adf..93dd1dc 100644
--- a/tools/rpmdb2solv.c
+++ b/tools/rpmdb2solv.c
@@ -20,6 +20,11 @@
#include <string.h>
#include <unistd.h>
+#ifdef ENABLE_RPMDB_LIBRPM
+#include <rpm/rpmmacro.h>
+#endif
+
+
#include "pool.h"
#include "repo.h"
#include "repo_rpmdb.h"
@@ -64,6 +69,7 @@ main(int argc, char **argv)
int nopacks = 0;
int add_changelog = 0;
const char *root = 0;
+ const char *dbpath = 0;
const char *refname = 0;
#ifdef ENABLE_SUSEREPO
char *proddir = 0;
@@ -83,7 +89,7 @@ main(int argc, char **argv)
* parse arguments
*/
- while ((c = getopt(argc, argv, "ACPhnkxXr:p:o:")) >= 0)
+ while ((c = getopt(argc, argv, "ACD:PhnkxXr:p:o:")) >= 0)
switch (c)
{
case 'h':
@@ -92,6 +98,9 @@ main(int argc, char **argv)
case 'r':
root = optarg;
break;
+ case 'D':
+ dbpath = optarg;
+ break;
case 'n':
nopacks = 1;
break;
@@ -160,6 +169,21 @@ main(int argc, char **argv)
if (root && *root)
pool_set_rootdir(pool, root);
+#ifdef ENABLE_PUBKEY
+ if (dbpath && *dbpath && (!nopacks || pubkeys))
+#else
+ if (dbpath && *dbpath && !nopacks)
+#endif
+ {
+#ifdef ENABLE_RPMDB_LIBRPM
+ char *macro = solv_dupjoin("_dbpath ", dbpath, 0);
+ rpmDefineMacro(NULL, macro, 0);
+ free(macro);
+#else
+ fprintf(stderr, "cannot set dbpath without librpm\n");
+ exit(1);
+#endif
+ }
repo = repo_create(pool, "installed");
data = repo_add_repodata(repo, 0);