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
SET(LIBSOLV_MAJOR "0")
SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "16")
+SET(LIBSOLV_PATCH "17")
#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 {
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
.\" 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
.\" -----------------------------------------------------------------
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
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\&.
*-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
* TODO:
*
* what's the difference between group/category?
- * handle "default" and "langonly".
*
* maybe handle REL_COND in solver recommends handling?
*/
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)
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:
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;
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:
#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);
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 */
*
*/
+#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmmacro.h>
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 */
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";
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)
{
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));
Id handle;
Solvable *solvable;
time_t buildtime;
- Id collhandle;
+ Id pkghandle;
struct solv_xmlparser xmlp;
struct joindata jd;
+ Id collhandle;
};
/*
}
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">
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:
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;
}
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> */
{
/* 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;
{
/* 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;
{
/* 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:
Id *genid = 0;
int ngenid = 0;
Queue autoinstq;
+ int oldjobsize = job ? job->count : 0;
if (resultp)
*resultp = 0;
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)
{
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)
{
-------------------------------------------------------------------
+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
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)
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;
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)
{
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)
--- /dev/null
+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
--- /dev/null
+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
#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"
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;
* 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':
case 'r':
root = optarg;
break;
+ case 'D':
+ dbpath = optarg;
+ break;
case 'n':
nopacks = 1;
break;
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);