This file contains the major changes between
libsolv versions:
+Version 0.7.20
+- selected bug fixes:
+ * fix misparsing of '&' in attributes with libxml2
+ * choice rules: treat orphaned packages as newest
+ * fix compatibility with Python 3.10
+- new features:
+ * new SOLVER_EXCLUDEFROMWEAK job to ignore pkgs for weak dependencies
+ * support for environments in comps parser
+
Version 0.7.19
- selected bug fixes:
* fix rare segfault in resolve_jobrules() that could happen
SET(LIBSOLV_MAJOR "0")
SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "19")
+SET(LIBSOLV_PATCH "20")
%markfunc Pool "mark_Pool";
#endif
+#ifdef SWIGPYTHON
+%begin %{
+#define PY_SSIZE_T_CLEAN
+%}
+#endif
+
/**
** binaryblob handling
**/
$2 = size;
}
-%typemap(freearg,noblock=1,match="in") (const unsigned char *str, int len) {
+%typemap(freearg,noblock=1,match="in") (const unsigned char *str, size_t len) {
if (alloc$argnum == SWIG_NEWOBJ) %delete_array(buf$argnum);
}
%typemap(out,noblock=1,fragment="SWIG_FromCharPtrAndSize") BinaryBlob {
#if defined(SWIGPYTHON) && defined(PYTHON3)
- $result = $1.data ? Py_BuildValue("y#", $1.data, $1.len) : SWIG_Py_Void();
+ $result = $1.data ? Py_BuildValue("y#", $1.data, (Py_ssize_t)$1.len) : SWIG_Py_Void();
#elif defined(SWIGTCL)
Tcl_SetObjResult(interp, $1.data ? Tcl_NewByteArrayObj($1.data, $1.len) : NULL);
#else
static const Id SOLVER_ALLOWUNINSTALL = SOLVER_ALLOWUNINSTALL;
static const Id SOLVER_FAVOR = SOLVER_FAVOR;
static const Id SOLVER_DISFAVOR = SOLVER_DISFAVOR;
+ static const Id SOLVER_EXCLUDEFROMWEAK = SOLVER_EXCLUDEFROMWEAK;
static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
static const Id SOLVER_WEAK = SOLVER_WEAK;
static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
can also be used to block recommended or supplemented packages from being
installed.
+*SOLVER_EXCLUDEFROMWEAK*::
+Avoid the specified packages to satisfy recommended or supplemented dependencies.
+Unlike SOLVER_DISFAVOR, it does not interfere with other rules.
+
*SOLVER_JOBMASK*::
A mask containing all the above action bits.
STATE_CDISPLAY_ORDER,
STATE_GROUPLIST,
STATE_GROUPID,
+ STATE_ENVIRONMENT,
+ STATE_OPTIONLIST,
NUMSTATES
};
{ STATE_START, "comps", STATE_COMPS, 0 },
{ STATE_COMPS, "group", STATE_GROUP, 0 },
{ STATE_COMPS, "category", STATE_CATEGORY, 0 },
+ { STATE_COMPS, "environment", STATE_ENVIRONMENT, 0 },
{ STATE_GROUP, "id", STATE_ID, 1 },
{ STATE_GROUP, "name", STATE_NAME, 1 },
{ STATE_GROUP, "description", STATE_DESCRIPTION, 1 },
{ STATE_CATEGORY , "grouplist", STATE_GROUPLIST, 0 },
{ STATE_CATEGORY , "display_order", STATE_DISPLAY_ORDER, 1 },
{ STATE_GROUPLIST, "groupid", STATE_GROUPID, 1 },
+ { STATE_ENVIRONMENT, "id", STATE_ID, 1 },
+ { STATE_ENVIRONMENT, "name", STATE_NAME, 1 },
+ { STATE_ENVIRONMENT, "description", STATE_DESCRIPTION, 1 },
+ { STATE_ENVIRONMENT, "grouplist", STATE_GROUPLIST, 0 },
+ { STATE_ENVIRONMENT, "optionlist", STATE_OPTIONLIST, 0 },
+ { STATE_ENVIRONMENT, "display_order", STATE_DISPLAY_ORDER, 1 },
+ { STATE_OPTIONLIST, "groupid", STATE_GROUPID, 1 },
{ NUMSTATES }
};
{
case STATE_GROUP:
case STATE_CATEGORY:
+ case STATE_ENVIRONMENT:
s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
pd->handle = s - pool->solvables;
- pd->kind = state == STATE_GROUP ? "group" : "category";
+ if (state == STATE_GROUP)
+ pd->kind = "group";
+ else if (state == STATE_CATEGORY)
+ pd->kind = "category";
+ else
+ pd->kind = "environment";
pd->isvisible = COMPS_DEFAULT_ISVISIBLE;
pd->isdefault = COMPS_DEFAULT_ISDEFAULT;
break;
break;
}
+ case STATE_GROUPLIST:
+ {
+ pd->reqtype = SOLVABLE_REQUIRES;
+ break;
+ }
+
+ case STATE_OPTIONLIST:
+ {
+ pd->reqtype = SOLVABLE_SUGGESTS;
+ break;
+ }
+
default:
break;
}
{
case STATE_GROUP:
case STATE_CATEGORY:
+ case STATE_ENVIRONMENT:
if (!s->arch)
s->arch = ARCH_NOARCH;
if (!s->evr)
case STATE_GROUPID:
id = pool_str2id(pd->pool, join2(&pd->jd, "group", ":", content), 1);
- s->requires = repo_addid_dep(pd->repo, s->requires, id, 0);
+ repo_add_idarray(pd->repo, pd->handle, pd->reqtype, id);
break;
case STATE_USERVISIBLE:
tmp = solvable_lookup_str(s, SOLVABLE_BUILDVERSION);
if (tmp)
fprintf(fp, "=Bvr: %s\n", tmp);
+ if (solvable_lookup_idarray(s, SOLVABLE_TRACK_FEATURES, &q))
+ {
+ int i;
+ for (i = 0; i < q.count; i++)
+ fprintf(fp, "=Trf: %s\n", pool_id2str(pool, q.elements[i]));
+ }
ti = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0);
if (ti)
fprintf(fp, "=Tim: %u\n", ti);
case 'B' << 16 | 'v' << 8 | 'r':
repodata_set_str(data, s - pool->solvables, SOLVABLE_BUILDVERSION, line + 6);
break;
+ case 'T' << 16 | 'r' << 8 | 'f':
+ repodata_add_poolstr_array(data, s - pool->solvables, SOLVABLE_TRACK_FEATURES, line + 6);
+ break;
default:
break;
}
}
#ifdef WITH_LIBXML2
+static void fixup_att_inplace(char *at)
+{
+ while ((at = strchr(at, '&')) != 0)
+ {
+ at++;
+ if (!memcmp(at, "#38;", 4))
+ memmove(at, at + 4, strlen(at + 4) + 1);
+ }
+}
+
+static const xmlChar **fixup_atts(struct solv_xmlparser *xmlp, const xmlChar **atts)
+{
+ size_t needsize = 0;
+ size_t natts;
+ char **at;
+
+ for (natts = 0; atts[natts]; natts++)
+ if (strchr((char *)atts[natts], '&'))
+ needsize += strlen((const char *)atts[natts]) + 1;
+ if (!needsize)
+ return atts;
+ at = xmlp->attsdata = solv_realloc(xmlp->attsdata, (natts + 1) * sizeof(xmlChar *) + needsize);
+ needsize = (natts + 1) * sizeof(xmlChar *);
+ for (natts = 0; atts[natts]; natts++)
+ {
+ at[natts] = (char *)atts[natts];
+ if (strchr(at[natts], '&'))
+ {
+ size_t l = strlen(at[natts]) + 1;
+ memcpy((char *)at + needsize, at[natts], l);
+ at[natts] = (char *)at + needsize;
+ needsize += l;
+ fixup_att_inplace(at[natts]);
+ }
+ }
+ at[natts] = 0;
+ return (const xmlChar **)at;
+}
+#endif
+
+#ifdef WITH_LIBXML2
static void
start_element(void *userData, const xmlChar *name, const xmlChar **atts)
#else
static const char *nullattr;
atts = (const xmlChar **)&nullattr;
}
+ else if (xmlp->state != oldstate)
+ atts = fixup_atts(xmlp, atts);
#endif
if (xmlp->state != oldstate)
xmlp->startelement(xmlp, xmlp->state, el->element, (const char **)atts);
queue_free(&xmlp->elementq);
xmlp->content = solv_free(xmlp->content);
xmlp->errstr = solv_free(xmlp->errstr);
+ xmlp->attsdata = solv_free(xmlp->attsdata);
}
static void
Id *elementhelper;
void *parser;
+ void *attsdata;
};
#define SOLV_XMLPARSER_OK 0
{ SOLVER_FAVOR, "favor" },
{ SOLVER_DISFAVOR, "disfavor" },
{ SOLVER_BLACKLIST, "blacklist" },
+ { SOLVER_EXCLUDEFROMWEAK, "excludefromweak" },
{ 0, 0 }
};
-------------------------------------------------------------------
+Sat Sep 25 22:45:07 CEST 2021 - mls@suse.de
+
+- fix misparsing of '&' in attributes with libxml2
+- choice rules: treat orphaned packages as newest [bsc#1190465]
+- fix compatibility with Python 3.10
+- new SOLVER_EXCLUDEFROMWEAK job type
+- support for environments in comps parser
+
+-------------------------------------------------------------------
+Fri Jul 30 11:43:29 UTC 2021 - Dominique Leuenberger <dimstar@opensuse.org>
+
+- Disable python2 usage on suse_version >= 1550 by default (still
+ possible to use osc build --with=python).
+
+-------------------------------------------------------------------
Wed Apr 7 14:56:16 CEST 2021 - mls@suse.de
- fix rare segfault in resolve_jobrules() that could happen
#
# spec file for package libsolv
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2021 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
+
%define libname libsolv@LIBSOLV_SOVERSION@
%if 0%{?sle_version} >= 120300 || 0%{?suse_version} >= 1330 || !0%{?suse_version}
# we need at least swig 1.3.40 for the bindings ($typemap support)
%if 0%{?suse_version} != 1110
%bcond_without python3
+%if 0%{?suse_version} < 1550
%bcond_without python
+%else
+%bcond_with python
+%endif
%bcond_without ruby
%bcond_without perl
%else
Summary: Package dependency solver using a satisfiability algorithm
License: BSD-3-Clause
Group: Development/Libraries/C and C++
-Url: https://github.com/openSUSE/libsolv
+URL: https://github.com/openSUSE/libsolv
Source: libsolv-%{version}.tar.bz2
BuildRequires: cmake
BuildRequires: gcc-c++
BuildRequires: libzstd-devel
%endif
-
%description
libsolv is a library for solving packages and reading repositories.
The solver uses a satisfiability algorithm.
if (build)
{
*p++ = ' ';
- memcpy(p, build, buildend - build);
+ memmove(p, build, buildend - build);
p += buildend - build;
}
evrid = pool_strn2id(pool, version, p - version, 1);
if (!ur->p)
ur = solv->rules + solv->featurerules + (pi - pool->installed->start);
if (!ur->p)
- return 0;
+ return 1; /* orphaned, thus newest */
queue_push2(q, pi, 0);
FOR_RULELITERALS(p, pp, ur)
if (p > 0 && p != pi)
map_free(&solv->droporphanedmap);
map_free(&solv->cleandepsmap);
map_free(&solv->allowuninstallmap);
+ map_free(&solv->excludefromweakmap);
+
solv_free(solv->favormap);
solv_free(solv->decisionmap);
queue_truncate(plist, j);
}
+static void
+prune_exclude_from_weak(Solver *solv, Queue *plist)
+{
+ int i, j;
+ for (i = j = 0; i < plist->count; i++)
+ {
+ Id p = plist->elements[i];
+ if (!MAPTST(&solv->excludefromweakmap, p))
+ plist->elements[j++] = p;
+ }
+ if (i != j)
+ queue_truncate(plist, j);
+}
+
static int
resolve_weak(Solver *solv, int level, int disablerules, Queue *dq, Queue *dqs, int *rerunp)
{
continue;
if (solv->havedisfavored && solv->favormap[i] < 0)
continue; /* disfavored supplements, do not install */
+ if (solv->excludefromweakmap.size && MAPTST(&solv->excludefromweakmap, i))
+ continue; /* excluded for weak deps, do not install */
queue_push(dqs, i);
}
}
if (dq->count && solv->havedisfavored)
prune_disfavored(solv, dq);
+ /* filter out weak_excluded recommended packages */
+ if (solv->excludefromweakmap.size)
+ prune_exclude_from_weak(solv, dq);
+
/* filter out all packages obsoleted by installed packages */
/* this is no longer needed if we have (and trust) reverse obsoletes */
if ((dqs->count || dq->count) && solv->installed)
#endif
static void
+solver_add_exclude_from_weak(Solver *solv)
+{
+ Queue *job = &solv->job;
+ Pool *pool = solv->pool;
+ int i;
+ Id p, pp, how, what, select;
+for (i = 0; i < job->count; i += 2)
+ {
+ how = job->elements[i];
+ if ((how & SOLVER_JOBMASK) != SOLVER_EXCLUDEFROMWEAK)
+ continue;
+ if (!solv->excludefromweakmap.size)
+ map_grow(&solv->excludefromweakmap, pool->nsolvables);
+ what = job->elements[i + 1];
+ select = how & SOLVER_SELECTMASK;
+ if (select == SOLVER_SOLVABLE_REPO)
+ {
+ Repo *repo = pool_id2repo(pool, what);
+ if (repo)
+ {
+ Solvable *s;
+ FOR_REPO_SOLVABLES(repo, p, s)
+ MAPSET(&solv->excludefromweakmap, p);
+ }
+ }
+ FOR_JOB_SELECT(p, pp, select, what)
+ MAPSET(&solv->excludefromweakmap, p);
+ }
+}
+
+static void
setup_favormap(Solver *solv)
{
Queue *job = &solv->job;
int hasfavorjob = 0;
int haslockjob = 0;
int hasblacklistjob = 0;
+ int hasexcludefromweakjob = 0;
solve_start = solv_timems(0);
map_zerosize(&solv->droporphanedmap);
solv->allowuninstall_all = 0;
map_zerosize(&solv->allowuninstallmap);
+ map_zerosize(&solv->excludefromweakmap);
map_zerosize(&solv->cleandepsmap);
map_zerosize(&solv->weakrulemap);
solv->favormap = solv_free(solv->favormap);
POOL_DEBUG(SOLV_DEBUG_JOB, "job: blacklist %s\n", solver_select2str(pool, select, what));
hasblacklistjob = 1;
break;
+ case SOLVER_EXCLUDEFROMWEAK:
+ POOL_DEBUG(SOLV_DEBUG_JOB, "job: excludefromweak %s\n", solver_select2str(pool, select, what));
+ hasexcludefromweakjob = 1;
+ break;
default:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
break;
else
solv->blackrules = solv->blackrules_end = solv->nrules;
+ if (hasexcludefromweakjob)
+ solver_add_exclude_from_weak(solv);
+
if (solv->havedisfavored && solv->strongrecommends && solv->recommendsruleq)
solver_addrecommendsrules(solv);
else
Map allowuninstallmap; /* ok to uninstall those */
int allowuninstall_all;
+ Map excludefromweakmap; /* remove them from candidates for supplements and recommends */
+
Id *favormap; /* favor job index, > 0: favored, < 0: disfavored */
int havedisfavored; /* do we have disfavored packages? */
#define SOLVER_FAVOR 0x0c00
#define SOLVER_DISFAVOR 0x0d00
#define SOLVER_BLACKLIST 0x0e00
+#define SOLVER_EXCLUDEFROMWEAK 0x1000
#define SOLVER_JOBMASK 0xff00
--- /dev/null
+repo @System 0 testtags <inline>
+#>=Pkg: pkg-A 1.0 1 noarch
+#>=Prv: pkg-A = 1.0-1
+#>=Rec: pkg-C
+#>=Pkg: pkg-B 1.0 1 noarch
+#>=Prv: pkg-B = 1.0-1
+
+repo available -99.-1000 testtags <inline>
+#>=Pkg: pkg-A 1.0 3 noarch
+#>=Prv: pkg-A = 1.0-3
+#>=Rec: pkg-B
+#>=Pkg: pkg-B 1.0 2 noarch
+#>=Prv: pkg-B = 1.0-2
+#>=Pkg: pkg-C 1.0 1 noarch
+#>=Prv: pkg-C = 1.0-1
+#>=Obs: pkg-B
+
+system x86_64 rpm @System
+poolflags implicitobsoleteusescolors
+solverflags allowvendorchange keepexplicitobsoletes bestobeypolicy keeporphans yumobsoletes
+
+job update all packages [forcebest]
+job excludefromweak name pkg-C
+result transaction,problems <inline>
+#>erase pkg-B-1.0-1.noarch@@System pkg-C-1.0-1.noarch@available
+#>install pkg-C-1.0-1.noarch@available
+#>upgrade pkg-A-1.0-1.noarch@@System pkg-A-1.0-3.noarch@available
+
+nextjob
+job update oneof pkg-A-1.0-1.noarch@@System pkg-B-1.0-1.noarch@@System pkg-A-1.0-3.noarch@available pkg-B-1.0-2.noarch@available pkg-C-1.0-1.noarch@available [forcebest,targeted,setevr,setarch]
+job excludefromweak name pkg-C
+result transaction,problems <inline>
+#>erase pkg-B-1.0-1.noarch@@System pkg-C-1.0-1.noarch@available
+#>install pkg-C-1.0-1.noarch@available
+#>upgrade pkg-A-1.0-1.noarch@@System pkg-A-1.0-3.noarch@available
--- /dev/null
+repo @System 0 testtags <inline>
+
+repo available -99.-1000 testtags <inline>
+#>=Pkg: pkg-A 1 1 noarch
+#>=Prv: pkg-A = 1-1
+#>=Rec: pkg-B
+#>=Pkg: pkg-B 1 1 noarch
+#>=Prv: pkg-B = 1-1
+
+system x86_64 rpm @System
+poolflags implicitobsoleteusescolors
+solverflags allowvendorchange keepexplicitobsoletes bestobeypolicy keeporphans yumobsoletes
+
+job install oneof pkg-A-1-1.noarch@available [forcebest,targeted,setevr,setarch]
+job excludefromweak name pkg-B
+result transaction,problems <inline>
+#>install pkg-A-1-1.noarch@available
+
+nextjob
+job install oneof pkg-A-1-1.noarch@available [forcebest,targeted,setevr,setarch]
+job excludefromweak name pkg-A
+job excludefromweak name pkg-B
+result transaction,problems <inline>
+#>install pkg-A-1-1.noarch@available