summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:38:58 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:39:53 +0900
commit22e701e553344eeb22f88ed0906d76c9a5e39d83 (patch)
tree493781d54b4af93dc853e86a0be040d1da95a13c
parentf458102388250c8a1cbbfa8f18d27baa204c696c (diff)
downloadlibsolv-22e701e553344eeb22f88ed0906d76c9a5e39d83.tar.gz
libsolv-22e701e553344eeb22f88ed0906d76c9a5e39d83.tar.bz2
libsolv-22e701e553344eeb22f88ed0906d76c9a5e39d83.zip
Imported Upstream version 0.6.24upstream/0.6.24
Change-Id: I68f4d40b704c1ccd2a86576a3c03687922f023aa Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
-rw-r--r--CMakeLists.txt8
-rw-r--r--NEWS4
-rw-r--r--VERSION.cmake2
-rw-r--r--bindings/CMakeLists.txt3
-rw-r--r--bindings/python/CMakeLists.txt13
-rw-r--r--bindings/python3/CMakeLists.txt35
-rw-r--r--bindings/solv.i5
-rw-r--r--examples/solv/patchjobs.c6
-rw-r--r--ext/CMakeLists.txt8
-rw-r--r--ext/libsolvext.ver1
-rw-r--r--ext/repo_rpmdb.c266
-rw-r--r--ext/repo_susetags.c89
-rw-r--r--ext/testcase.c45
-rw-r--r--package/libsolv.changes10
-rw-r--r--package/libsolv.spec.in31
-rw-r--r--src/order.c6
-rw-r--r--src/problems.c30
-rw-r--r--src/rules.c12
-rw-r--r--src/selection.c34
-rw-r--r--src/solver.c1608
-rw-r--r--src/solver.h13
-rw-r--r--src/solvversion.h.in1
-rw-r--r--test/testcases/focus/best.t23
-rw-r--r--test/testcases/focus/installed.t23
-rw-r--r--test/testcases/focus/normal.t22
-rw-r--r--tools/CMakeLists.txt11
-rw-r--r--tools/installcheck.c9
27 files changed, 1304 insertions, 1014 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0153a70..82034e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@ OPTION (ENABLE_TCL "Build the Tcl bindings?" OFF)
OPTION (USE_VENDORDIRS "Install the bindings in vendor directories?" OFF)
OPTION (ENABLE_RPMDB "Build with rpm database support?" OFF)
+OPTION (ENABLE_RPMPKG "Build with rpm package support?" OFF)
OPTION (ENABLE_PUBKEY "Build with pubkey support?" OFF)
OPTION (ENABLE_RPMDB_BYRPMHEADER "Build with rpmdb Header support?" OFF)
OPTION (ENABLE_RPMMD "Build with rpmmd repository support?" OFF)
@@ -174,6 +175,10 @@ IF (MULTI_SEMANTICS)
MESSAGE (STATUS "Enabling multi dist support")
ENDIF (MULTI_SEMANTICS)
+IF (ENABLE_RPMDB)
+SET (ENABLE_RPMPKG ON)
+ENDIF (ENABLE_RPMDB)
+
INCLUDE (CheckIncludeFile)
IF (ENABLE_RPMDB)
FIND_LIBRARY (RPMDB_LIBRARY NAMES rpmdb)
@@ -254,7 +259,8 @@ FOREACH (VAR
ENDFOREACH (VAR)
FOREACH (VAR
- ENABLE_RPMDB ENABLE_PUBKEY ENABLE_RPMMD ENABLE_RPMDB_BYRPMHEADER ENABLE_SUSEREPO ENABLE_COMPS
+ ENABLE_RPMDB ENABLE_RPMPKG ENABLE_PUBKEY ENABLE_RPMMD ENABLE_RPMDB_BYRPMHEADER
+ ENABLE_SUSEREPO ENABLE_COMPS
ENABLE_HELIXREPO ENABLE_MDKREPO ENABLE_ARCHREPO ENABLE_DEBIAN ENABLE_HAIKU
ENABLE_LZMA_COMPRESSION ENABLE_BZIP2_COMPRESSION ENABLE_PGPVRFY ENABLE_APPDATA)
IF(${VAR})
diff --git a/NEWS b/NEWS
index 1745af8..79e18dc 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@
This file contains the major changes between
libsolv versions:
+Version 0.6.24
+- new features:
+ * new SOLVER_FLAG_FOCUS_BEST flag
+
Version 0.6.22, 0.6.23
- bug fix releases, no new features
diff --git a/VERSION.cmake b/VERSION.cmake
index 10ade66..ffa5bd0 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "0")
SET(LIBSOLV_MAJOR "0")
SET(LIBSOLV_MINOR "6")
-SET(LIBSOLV_PATCH "23")
+SET(LIBSOLV_PATCH "24")
diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt
index 34b0784..737cee4 100644
--- a/bindings/CMakeLists.txt
+++ b/bindings/CMakeLists.txt
@@ -8,6 +8,9 @@ SET (SWIG_INPUT "${CMAKE_CURRENT_SOURCE_DIR}/solv.i")
IF (ENABLE_PYTHON)
ADD_SUBDIRECTORY (python)
ENDIF (ENABLE_PYTHON)
+IF (ENABLE_PYTHON3)
+ ADD_SUBDIRECTORY (python3)
+ENDIF (ENABLE_PYTHON3)
IF (ENABLE_PERL)
ADD_SUBDIRECTORY (perl)
ENDIF (ENABLE_PERL)
diff --git a/bindings/python/CMakeLists.txt b/bindings/python/CMakeLists.txt
index 73f2dca..dc6648d 100644
--- a/bindings/python/CMakeLists.txt
+++ b/bindings/python/CMakeLists.txt
@@ -1,7 +1,13 @@
-#SET (PythonLibs_FIND_VERSION 3)
-
-FIND_PACKAGE (PythonLibs)
+IF (ENABLE_PYTHON3 AND NOT DEFINED PythonLibs_FIND_VERSION)
+ # if we build both for python2 and python3, make this the python2 build.
+ # see comment in the python3 CMakeLists.txt file
+ SET (PythonLibs_FIND_VERSION 2)
+ SET (PythonLibs_FIND_VERSION_MAJOR 2)
+ENDIF (ENABLE_PYTHON3 AND NOT DEFINED PythonLibs_FIND_VERSION)
+
+FIND_PACKAGE (PythonLibs REQUIRED)
FIND_PACKAGE (PythonInterp ${PYTHONLIBS_VERSION_STRING} 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)
IF (NOT DEFINED PYTHON_VERSION_MAJOR)
@@ -13,6 +19,7 @@ ENDIF (${PYTHON_VERSION_MAJOR} GREATER 2)
MESSAGE (STATUS "Python executable: ${PYTHON_EXECUTABLE}")
MESSAGE (STATUS "Python installation dir: ${PYTHON_INSTALL_DIR}")
+MESSAGE (STATUS "Python include path: ${PYTHON_INCLUDE_PATH}")
ADD_CUSTOM_COMMAND (
OUTPUT solv_python.c
diff --git a/bindings/python3/CMakeLists.txt b/bindings/python3/CMakeLists.txt
new file mode 100644
index 0000000..7a2dca3
--- /dev/null
+++ b/bindings/python3/CMakeLists.txt
@@ -0,0 +1,35 @@
+#
+# used for building both python2 and python3 bindings
+# do not use if you want to build just one flavor, use the
+# standard python bindings file in that case.
+#
+# we cannot use FIND_PACKAGE PythonLibs here, as this would
+# clash with the python variables.
+#
+IF (NOT DEFINED ${PYTHON3_EXECUTABLE})
+SET (PYTHON3_EXECUTABLE "/usr/bin/python3")
+ENDIF (NOT DEFINED ${PYTHON3_EXECUTABLE})
+
+EXECUTE_PROCESS(COMMAND ${PYTHON3_EXECUTABLE} -c "from sys import stdout; from distutils import sysconfig; stdout.write(sysconfig.get_python_lib(True))" OUTPUT_VARIABLE PYTHON3_INSTALL_DIR)
+EXECUTE_PROCESS(COMMAND ${PYTHON3_EXECUTABLE} -c "from sys import stdout; from distutils import sysconfig; stdout.write(sysconfig.get_python_inc())" OUTPUT_VARIABLE PYTHON3_INCLUDE_DIR)
+
+MESSAGE (STATUS "Python3 executable: ${PYTHON3_EXECUTABLE}")
+MESSAGE (STATUS "Python3 installation dir: ${PYTHON3_INSTALL_DIR}")
+MESSAGE (STATUS "Python3 include path: ${PYTHON3_INCLUDE_DIR}")
+
+ADD_CUSTOM_COMMAND (
+ OUTPUT solv_python.c
+ COMMAND ${SWIG_EXECUTABLE} ${SWIG_FLAGS} -python -DPYTHON3=1 -I${CMAKE_SOURCE_DIR}/src -o solv_python.c ${CMAKE_SOURCE_DIR}/bindings/solv.i
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${CMAKE_SOURCE_DIR}/bindings/solv.i
+)
+
+ADD_DEFINITIONS(-Wno-unused)
+INCLUDE_DIRECTORIES (${PYTHON3_INCLUDE_DIR})
+
+ADD_LIBRARY (bindings_python3 SHARED solv_python.c)
+SET_TARGET_PROPERTIES (bindings_python3 PROPERTIES PREFIX "" OUTPUT_NAME "_solv")
+TARGET_LINK_LIBRARIES (bindings_python3 libsolvext libsolv ${SYSTEM_LIBRARIES})
+
+INSTALL (TARGETS bindings_python3 LIBRARY DESTINATION ${PYTHON3_INSTALL_DIR})
+INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/solv.py DESTINATION ${PYTHON3_INSTALL_DIR})
diff --git a/bindings/solv.i b/bindings/solv.i
index b21fbbc..64f51d0 100644
--- a/bindings/solv.i
+++ b/bindings/solv.i
@@ -634,7 +634,7 @@ typedef int bool;
#include "selection.h"
#include "repo_write.h"
-#ifdef ENABLE_RPMDB
+#if defined(ENABLE_RPMDB) || defined(ENABLE_RPMPKG)
#include "repo_rpmdb.h"
#endif
#ifdef ENABLE_PUBKEY
@@ -1990,6 +1990,8 @@ rb_eval_string(
bool add_rpmdb_reffp(FILE *reffp, int flags = 0) {
return repo_add_rpmdb_reffp($self, reffp, flags) == 0;
}
+#endif
+#ifdef ENABLE_RPMPKG
%newobject add_rpm;
XSolvable *add_rpm(const char *name, int flags = 0) {
return new_XSolvable($self->pool, repo_add_rpm($self, name, flags));
@@ -3278,6 +3280,7 @@ rb_eval_string(
static const int SOLVER_FLAG_FOCUS_INSTALLED = SOLVER_FLAG_FOCUS_INSTALLED;
static const int SOLVER_FLAG_YUM_OBSOLETES = SOLVER_FLAG_YUM_OBSOLETES;
static const int SOLVER_FLAG_NEED_UPDATEPROVIDE = SOLVER_FLAG_NEED_UPDATEPROVIDE;
+ static const int SOLVER_FLAG_FOCUS_BEST = SOLVER_FLAG_FOCUS_BEST;
static const int SOLVER_REASON_UNRELATED = SOLVER_REASON_UNRELATED;
static const int SOLVER_REASON_UNIT_RULE = SOLVER_REASON_UNIT_RULE;
diff --git a/examples/solv/patchjobs.c b/examples/solv/patchjobs.c
index 64ad607..929a203 100644
--- a/examples/solv/patchjobs.c
+++ b/examples/solv/patchjobs.c
@@ -19,8 +19,10 @@ add_patchjobs(Pool *pool, Queue *job)
map_init(&installedmap, pool->nsolvables);
solver_calculate_multiversionmap(pool, job, &multiversionmap);
if (pool->installed)
- FOR_REPO_SOLVABLES(pool->installed, p, s)
- MAPSET(&installedmap, p);
+ {
+ FOR_REPO_SOLVABLES(pool->installed, p, s)
+ MAPSET(&installedmap, p);
+ }
/* install all patches */
for (p = 1; p < pool->nsolvables; p++)
diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt
index ec5f20c..586eda8 100644
--- a/ext/CMakeLists.txt
+++ b/ext/CMakeLists.txt
@@ -4,12 +4,12 @@ SET (libsolvext_SRCS
SET (libsolvext_HEADERS
tools_util.h solv_xfopen.h testcase.h)
-IF (ENABLE_RPMDB)
+IF (ENABLE_RPMDB OR ENABLE_RPMPKG)
SET (libsolvext_SRCS ${libsolvext_SRCS}
pool_fileconflicts.c repo_rpmdb.c)
SET (libsolvext_HEADERS ${libsolvext_HEADERS}
pool_fileconflicts.h repo_rpmdb.h)
-ENDIF (ENABLE_RPMDB)
+ENDIF (ENABLE_RPMDB OR ENABLE_RPMPKG)
IF (ENABLE_PUBKEY)
SET (libsolvext_SRCS ${libsolvext_SRCS}
@@ -45,12 +45,12 @@ ENDIF (ENABLE_SUSEREPO)
# old cmake does not support parenthetical expressions...
IF (ENABLE_COMPLEX_DEPS)
-IF (ENABLE_SUSEREPO OR ENABLE_RPMMD OR ENABLE_RPMDB)
+IF (ENABLE_SUSEREPO OR ENABLE_RPMMD OR ENABLE_RPMDB OR ENABLE_RPMPKG)
SET (libsolvext_SRCS ${libsolvext_SRCS}
pool_parserpmrichdep.c)
SET (libsolvext_HEADERS ${libsolvext_HEADERS}
pool_parserpmrichdep.h)
-ENDIF (ENABLE_SUSEREPO OR ENABLE_RPMMD OR ENABLE_RPMDB)
+ENDIF (ENABLE_SUSEREPO OR ENABLE_RPMMD OR ENABLE_RPMDB OR ENABLE_RPMPKG)
ENDIF (ENABLE_COMPLEX_DEPS)
IF (SUSE)
diff --git a/ext/libsolvext.ver b/ext/libsolvext.ver
index 8774fd4..4896e85 100644
--- a/ext/libsolvext.ver
+++ b/ext/libsolvext.ver
@@ -66,6 +66,7 @@ SOLV_1.0 {
testcase_str2dep;
testcase_str2job;
testcase_str2repo;
+ testcase_str2solvid;
testcase_read;
testcase_resultdiff;
testcase_solverresult;
diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c
index 95756c0..034198c 100644
--- a/ext/repo_rpmdb.c
+++ b/ext/repo_rpmdb.c
@@ -24,6 +24,8 @@
#include <stdint.h>
#include <errno.h>
+#ifdef ENABLE_RPMDB
+
#include <rpm/rpmio.h>
#include <rpm/rpmpgp.h>
#ifndef RPM5
@@ -39,6 +41,8 @@
# endif
#endif
+#endif
+
#include "pool.h"
#include "repo.h"
#include "hash.h"
@@ -162,10 +166,16 @@
# define RPM_INDEX_SIZE 8 /* rpmdbid + array index */
#endif
+/* some limits to guard against corrupt rpms */
+#define MAX_SIG_CNT 0x100000
+#define MAX_SIG_DSIZE 0x100000
+
+#define MAX_HDR_CNT 0x100000
+#define MAX_HDR_DSIZE 0x2000000
typedef struct rpmhead {
int cnt;
- int dcnt;
+ unsigned int dcnt;
unsigned char *dp;
int forcebinary; /* sigh, see rh#478907 */
unsigned char data[1];
@@ -204,7 +214,7 @@ headint32array(RpmHead *h, int tag, int *cnt)
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];
- if (o + 4 * i > h->dcnt)
+ if (o > h->dcnt || i > h->dcnt || o + 4 * i > h->dcnt)
return 0;
d = h->dp + o;
r = solv_calloc(i ? i : 1, sizeof(unsigned int));
@@ -226,7 +236,7 @@ headint32(RpmHead *h, int tag)
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];
- if (i == 0 || o + 4 * i > h->dcnt)
+ if (i == 0 || o > h->dcnt || i > h->dcnt || o + 4 * i > h->dcnt)
return 0;
d = h->dp + o;
return d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3];
@@ -243,7 +253,7 @@ headint64array(RpmHead *h, int tag, int *cnt)
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];
- if (o + 8 * i > h->dcnt)
+ if (o > h->dcnt || i > h->dcnt || o + 8 * i > h->dcnt)
return 0;
d = h->dp + o;
r = solv_calloc(i ? i : 1, sizeof(unsigned long long));
@@ -267,7 +277,7 @@ headint64(RpmHead *h, int tag)
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];
- if (i == 0 || o + 8 * i > h->dcnt)
+ if (i == 0 || o > h->dcnt || i > h->dcnt || o + 8 * i > h->dcnt)
return 0;
d = h->dp + o;
i = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3];
@@ -284,7 +294,7 @@ headint16array(RpmHead *h, int tag, int *cnt)
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];
- if (o + 4 * i > h->dcnt)
+ if (o > h->dcnt || i > h->dcnt || o + 2 * i > h->dcnt)
return 0;
d = h->dp + o;
r = solv_calloc(i ? i : 1, sizeof(unsigned int));
@@ -320,6 +330,8 @@ headstringarray(RpmHead *h, int tag, int *cnt)
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];
+ if (o > h->dcnt || i > h->dcnt)
+ return 0;
r = solv_calloc(i ? i : 1, sizeof(char *));
if (cnt)
*cnt = i;
@@ -347,7 +359,7 @@ headbinary(RpmHead *h, int tag, unsigned int *sizep)
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];
- if (o > h->dcnt || o + i < o || o + i > h->dcnt)
+ if (o > h->dcnt || i > h->dcnt || o + i > h->dcnt)
return 0;
if (sizep)
*sizep = i;
@@ -827,7 +839,7 @@ addfilelist(Repodata *data, Id handle, RpmHead *rpmhead, int flags)
Id did;
char *b = bn[i];
- if (di[i] == lastdii)
+ if (lastdid && di[i] == lastdii)
did = lastdid;
else
{
@@ -943,7 +955,7 @@ set_description_author(Repodata *data, Id handle, char *str)
}
static int
-rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, int flags)
+rpmhead2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, int flags)
{
char *name;
char *evr;
@@ -1075,6 +1087,12 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead,
return 1;
}
+static inline unsigned int
+getu32(const unsigned char *dp)
+{
+ return dp[0] << 24 | dp[1] << 16 | dp[2] << 8 | dp[3];
+}
+
/******************************************************************/
/* Rpm Database stuff
@@ -1087,13 +1105,17 @@ struct rpmdbstate {
RpmHead *rpmhead; /* header storage space */
int rpmheadsize;
+#ifdef ENABLE_RPMDB
int dbopened;
DB_ENV *dbenv; /* database environment */
DB *db; /* packages database */
int byteswapped; /* endianess of packages database */
int is_ostree; /* read-only db that lives in /usr/share/rpm */
+#endif
};
+#ifdef ENABLE_RPMDB
+
struct rpmdbentry {
Id rpmdbid;
Id nameoff;
@@ -1103,7 +1125,8 @@ struct rpmdbentry {
#define NAMEDATA_BLOCK 1023
-static inline Id db2rpmdbid(unsigned char *db, int byteswapped)
+static inline Id
+db2rpmdbid(unsigned char *db, int byteswapped)
{
#ifdef RPM5
return db[0] << 24 | db[1] << 16 | db[2] << 8 | db[3];
@@ -1119,7 +1142,8 @@ static inline Id db2rpmdbid(unsigned char *db, int byteswapped)
#endif
}
-static inline void rpmdbid2db(unsigned char *db, Id id, int byteswapped)
+static inline void
+rpmdbid2db(unsigned char *db, Id id, int byteswapped)
{
#ifdef RPM5
db[0] = id >> 24, db[1] = id >> 16, db[2] = id >> 8, db[3] = id;
@@ -1235,6 +1259,46 @@ closedbenv(struct rpmdbstate *state)
state->dbenv = 0;
}
+#endif
+
+static void
+freestate(struct rpmdbstate *state)
+{
+ /* close down */
+ if (!state)
+ return;
+#ifdef ENABLE_RPMDB
+ if (state->db)
+ state->db->close(state->db, 0);
+ if (state->dbenv)
+ closedbenv(state);
+#endif
+ if (state->rootdir)
+ solv_free(state->rootdir);
+ solv_free(state->rpmhead);
+}
+
+void *
+rpm_state_create(Pool *pool, const char *rootdir)
+{
+ struct rpmdbstate *state;
+ state = solv_calloc(1, sizeof(*state));
+ state->pool = pool;
+ if (rootdir)
+ state->rootdir = solv_strdup(rootdir);
+ return state;
+}
+
+void *
+rpm_state_free(void *state)
+{
+ freestate(state);
+ return solv_free(state);
+}
+
+
+#ifdef ENABLE_RPMDB
+
static int
openpkgdb(struct rpmdbstate *state)
{
@@ -1364,23 +1428,50 @@ getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *ma
return entries;
}
-/* retrive header by rpmdbid */
+/* common code, return dbid on success, -1 on error */
static int
-getrpmdbid(struct rpmdbstate *state, Id rpmdbid)
+getrpm_dbdata(struct rpmdbstate *state, DBT *dbdata, int dbid)
{
- unsigned char buf[16];
- DBT dbkey;
- DBT dbdata;
+ unsigned int dsize, cnt, l;
RpmHead *rpmhead;
- if (!rpmdbid)
+ if (dbdata->size < 8)
+ return pool_error(state->pool, -1, "corrupt rpm database (size)");
+ cnt = getu32((const unsigned char *)dbdata->data);
+ dsize = getu32((const unsigned char *)dbdata->data + 4);
+ if (cnt >= MAX_HDR_CNT || dsize >= MAX_HDR_DSIZE)
+ return pool_error(state->pool, -1, "corrupt rpm database (cnt/dcnt)");
+ l = cnt * 16 + dsize;
+ if (8 + l > dbdata->size)
+ return pool_error(state->pool, -1, "corrupt rpm database (data size)");
+ if (l + 1 > state->rpmheadsize)
{
- pool_error(state->pool, 0, "illegal rpmdbid");
- return -1;
+ state->rpmheadsize = l + 128;
+ 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);
+ rpmhead->data[l] = 0;
+ rpmhead->dp = rpmhead->data + cnt * 16;
+ return dbid;
+}
+
+/* retrive header by rpmdbid, returns 0 if not found, -1 on error */
+static int
+getrpm_dbid(struct rpmdbstate *state, Id dbid)
+{
+ unsigned char buf[4];
+ DBT dbkey;
+ DBT dbdata;
+
+ if (dbid <= 0)
+ return pool_error(state->pool, -1, "illegal rpmdbid %d", dbid);
if (state->dbopened != 1 && !openpkgdb(state))
return -1;
- rpmdbid2db(buf, rpmdbid, state->byteswapped);
+ rpmdbid2db(buf, dbid, state->byteswapped);
memset(&dbkey, 0, sizeof(dbkey));
memset(&dbdata, 0, sizeof(dbdata));
dbkey.data = buf;
@@ -1389,39 +1480,15 @@ getrpmdbid(struct rpmdbstate *state, Id rpmdbid)
dbdata.size = 0;
if (state->db->get(state->db, NULL, &dbkey, &dbdata, 0))
return 0;
- if (dbdata.size < 8)
- {
- pool_error(state->pool, 0, "corrupt rpm database (size)");
- return -1;
- }
- if (dbdata.size > state->rpmheadsize)
- {
- state->rpmheadsize = dbdata.size + 128;
- state->rpmhead = solv_realloc(state->rpmhead, sizeof(*rpmhead) + state->rpmheadsize);
- }
- rpmhead = state->rpmhead;
- memcpy(buf, dbdata.data, 8);
- rpmhead->forcebinary = 1;
- rpmhead->cnt = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
- rpmhead->dcnt = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7];
- if (8 + rpmhead->cnt * 16 + rpmhead->dcnt > dbdata.size)
- {
- pool_error(state->pool, 0, "corrupt rpm database (data size)");
- return -1;
- }
- memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt);
- rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
- return 1;
+ return getrpm_dbdata(state, &dbdata, dbid);
}
-/* retrive header by berkeleydb cursor */
+/* retrive header by berkeleydb cursor, returns 0 on EOF, -1 on error */
static Id
-getrpmcursor(struct rpmdbstate *state, DBC *dbc)
+getrpm_cursor(struct rpmdbstate *state, DBC *dbc)
{
- unsigned char buf[16];
DBT dbkey;
DBT dbdata;
- RpmHead *rpmhead;
Id dbid;
memset(&dbkey, 0, sizeof(dbkey));
@@ -1431,62 +1498,12 @@ getrpmcursor(struct rpmdbstate *state, DBC *dbc)
if (dbkey.size != 4)
return pool_error(state->pool, -1, "corrupt Packages database (key size)");
dbid = db2rpmdbid(dbkey.data, state->byteswapped);
- if (dbid == 0) /* the join key */
- continue;
- if (dbdata.size < 8)
- return pool_error(state->pool, -1, "corrupt rpm database (size %u)\n", dbdata.size);
- if (dbdata.size > state->rpmheadsize)
- {
- state->rpmheadsize = dbdata.size + 128;
- state->rpmhead = solv_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize);
- }
- rpmhead = state->rpmhead;
- memcpy(buf, dbdata.data, 8);
- rpmhead->forcebinary = 1;
- rpmhead->cnt = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
- rpmhead->dcnt = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7];
- if (8 + rpmhead->cnt * 16 + rpmhead->dcnt > dbdata.size)
- return pool_error(state->pool, -1, "corrupt rpm database (data size)\n");
- memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt);
- rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
- return dbid;
+ if (dbid) /* ignore join key */
+ return getrpm_dbdata(state, &dbdata, dbid);
}
return 0;
}
-static void
-freestate(struct rpmdbstate *state)
-{
- /* close down */
- if (!state)
- return;
- if (state->db)
- state->db->close(state->db, 0);
- if (state->dbenv)
- closedbenv(state);
- if (state->rootdir)
- solv_free(state->rootdir);
- solv_free(state->rpmhead);
-}
-
-void *
-rpm_state_create(Pool *pool, const char *rootdir)
-{
- struct rpmdbstate *state;
- state = solv_calloc(1, sizeof(*state));
- state->pool = pool;
- if (rootdir)
- state->rootdir = solv_strdup(rootdir);
- return state;
-}
-
-void *
-rpm_state_free(void *state)
-{
- freestate(state);
- return solv_free(state);
-}
-
static int
count_headers(struct rpmdbstate *state)
{
@@ -1851,7 +1868,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags)
}
i = 0;
s = 0;
- while ((dbid = getrpmcursor(&state, dbc)) != 0)
+ while ((dbid = getrpm_cursor(&state, dbc)) != 0)
{
if (dbid == -1)
{
@@ -1869,7 +1886,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags)
if (!repo->rpmdbid)
repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id));
repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid;
- if (rpm2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS))
+ if (rpmhead2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS))
{
i++;
s = 0;
@@ -2005,7 +2022,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags)
}
}
}
- res = getrpmdbid(&state, dbid);
+ res = getrpm_dbid(&state, dbid);
if (res <= 0)
{
if (!res)
@@ -2016,7 +2033,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags)
solv_free(refhash);
return -1;
}
- rpm2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS);
+ rpmhead2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS);
if ((flags & RPMDB_REPORT_PROGRESS) != 0)
{
if (done < count)
@@ -2071,12 +2088,7 @@ repo_add_rpmdb_reffp(Repo *repo, FILE *fp, int flags)
return res;
}
-static inline unsigned int
-getu32(const unsigned char *dp)
-{
- return dp[0] << 24 | dp[1] << 16 | dp[2] << 8 | dp[3];
-}
-
+#endif
Id
repo_add_rpm(Repo *repo, const char *rpm, int flags)
@@ -2148,7 +2160,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
}
sigcnt = getu32(lead + 96 + 8);
sigdsize = getu32(lead + 96 + 12);
- if (sigcnt >= 0x100000 || sigdsize >= 0x100000)
+ if (sigcnt >= MAX_SIG_CNT || sigdsize >= MAX_SIG_DSIZE)
{
pool_error(pool, -1, "%s: bad signature header", rpm);
fclose(fp);
@@ -2161,7 +2173,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
if ((flags & (RPM_ADD_WITH_PKGID | RPM_ADD_WITH_HDRID)) != 0)
{
/* extract pkgid or hdrid from the signature header */
- if (sigdsize > rpmheadsize)
+ if (sigdsize + 1 > rpmheadsize)
{
rpmheadsize = sigdsize + 128;
rpmhead = solv_realloc(rpmhead, sizeof(*rpmhead) + rpmheadsize);
@@ -2172,6 +2184,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
fclose(fp);
return 0;
}
+ rpmhead->data[sigdsize] = 0;
if (chksumh)
solv_chksum_add(chksumh, rpmhead->data, sigdsize);
if (leadsigchksumh)
@@ -2246,7 +2259,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
}
sigcnt = getu32(lead + 8);
sigdsize = getu32(lead + 12);
- if (sigcnt >= 0x100000 || sigdsize >= 0x2000000)
+ if (sigcnt >= MAX_HDR_CNT || sigdsize >= MAX_HDR_DSIZE)
{
pool_error(pool, -1, "%s: bad header", rpm);
fclose(fp);
@@ -2254,7 +2267,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
}
l = sigdsize + sigcnt * 16;
headerend = headerstart + 16 + l;
- if (l > rpmheadsize)
+ if (l + 1 > rpmheadsize)
{
rpmheadsize = l + 128;
rpmhead = solv_realloc(rpmhead, sizeof(*rpmhead) + rpmheadsize);
@@ -2265,6 +2278,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
fclose(fp);
return 0;
}
+ rpmhead->data[l] = 0;
if (chksumh)
solv_chksum_add(chksumh, rpmhead->data, l);
rpmhead->forcebinary = forcebinary;
@@ -2295,7 +2309,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags)
solv_chksum_add(chksumh, lead, l);
fclose(fp);
s = pool_id2solvable(pool, repo_add_solvable(repo));
- if (!rpm2solv(pool, repo, data, s, rpmhead, flags & ~(RPM_ADD_WITH_HDRID | RPM_ADD_WITH_PKGID)))
+ if (!rpmhead2solv(pool, repo, data, s, rpmhead, flags & ~(RPM_ADD_WITH_HDRID | RPM_ADD_WITH_PKGID)))
{
repo_free_solvable(repo, s - pool->solvables, 1);
solv_chksum_free(chksumh, 0);
@@ -2347,7 +2361,7 @@ repo_add_rpm_handle(Repo *repo, void *rpmhandle, int flags)
return 0;
}
s = pool_id2solvable(pool, repo_add_solvable(repo));
- if (!rpm2solv(pool, repo, data, s, rpmhead, flags))
+ if (!rpmhead2solv(pool, repo, data, s, rpmhead, flags))
{
repo_free_solvable(repo, s - pool->solvables, 1);
return 0;
@@ -2599,6 +2613,8 @@ rpm_query_num(void *rpmhandle, Id what, unsigned long long notfound)
return notfound;
}
+#ifdef ENABLE_RPMDB
+
int
rpm_installedrpmdbids(void *rpmstate, const char *index, const char *match, Queue *rpmdbidq)
{
@@ -2622,12 +2638,14 @@ rpm_byrpmdbid(void *rpmstate, Id rpmdbid)
struct rpmdbstate *state = rpmstate;
int r;
- r = getrpmdbid(state, rpmdbid);
+ r = getrpm_dbid(state, rpmdbid);
if (!r)
pool_error(state->pool, 0, "header #%d not in database", rpmdbid);
return r <= 0 ? 0 : state->rpmhead;
}
+#endif
+
void *
rpm_byfp(void *rpmstate, FILE *fp, const char *name)
{
@@ -2656,7 +2674,7 @@ rpm_byfp(void *rpmstate, FILE *fp, const char *name)
}
sigcnt = getu32(lead + 96 + 8);
sigdsize = getu32(lead + 96 + 12);
- if (sigcnt >= 0x100000 || sigdsize >= 0x100000)
+ if (sigcnt >= MAX_SIG_CNT || sigdsize >= MAX_SIG_DSIZE)
{
pool_error(state->pool, 0, "%s: bad signature header", name);
return 0;
@@ -2686,14 +2704,14 @@ rpm_byfp(void *rpmstate, FILE *fp, const char *name)
}
sigcnt = getu32(lead + 8);
sigdsize = getu32(lead + 12);
- if (sigcnt >= 0x100000 || sigdsize >= 0x2000000)
+ if (sigcnt >= MAX_HDR_CNT || sigdsize >= MAX_HDR_DSIZE)
{
pool_error(state->pool, 0, "%s: bad header", name);
return 0;
}
l = sigdsize + sigcnt * 16;
/* headerend = headerstart + 16 + l; */
- if (l > state->rpmheadsize)
+ if (l + 1 > state->rpmheadsize)
{
state->rpmheadsize = l + 128;
state->rpmhead = solv_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize);
@@ -2704,6 +2722,7 @@ rpm_byfp(void *rpmstate, FILE *fp, const char *name)
pool_error(state->pool, 0, "%s: unexpected EOF", name);
return 0;
}
+ rpmhead->data[l] = 0;
rpmhead->forcebinary = forcebinary;
rpmhead->cnt = sigcnt;
rpmhead->dcnt = sigdsize;
@@ -2730,19 +2749,22 @@ rpm_byrpmh(void *rpmstate, Header h)
return 0;
sigcnt = getu32(uh);
sigdsize = getu32(uh + 4);
+ if (sigcnt >= MAX_HDR_CNT || sigdsize >= MAX_HDR_DSIZE)
+ return 0;
l = sigdsize + sigcnt * 16;
- if (l > state->rpmheadsize)
+ if (l + 1 > state->rpmheadsize)
{
state->rpmheadsize = l + 128;
state->rpmhead = solv_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize);
}
rpmhead = state->rpmhead;
- memcpy(rpmhead->data, uh + 8, l - 8);
+ 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 + rpmhead->cnt * 16;
+ rpmhead->dp = rpmhead->data + sigcnt * 16;
return rpmhead;
}
diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c
index be73a7f..83967e0 100644
--- a/ext/repo_susetags.c
+++ b/ext/repo_susetags.c
@@ -330,7 +330,7 @@ commit_diskusage(struct parsedata *pd, Id handle)
*
*/
-static inline unsigned
+static inline unsigned int
tag_from_string(char *cs)
{
unsigned char *s = (unsigned char *)cs;
@@ -478,6 +478,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
Solvable *s;
Offset freshens;
int intag = 0;
+ int intag_linestart = 0;
int cummulate = 0;
int indesc = 0;
int indelta = 0;
@@ -558,10 +559,9 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
for (;;)
{
- unsigned tag;
- char *olinep; /* old line pointer */
+ unsigned int tag;
char line_lang[6];
- int keylen = 3;
+ int keylen;
if (pd.ret)
break;
@@ -574,84 +574,86 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
}
if (!fgets(linep, aline - (linep - line), fp)) /* read line */
break;
- olinep = linep;
linep += strlen(linep);
if (linep == line || linep[-1] != '\n')
continue;
pd.lineno++;
*--linep = 0;
- if (linep == olinep)
- continue;
if (intag)
{
- /* check for multi-line value tags (+Key:/-Key:) */
-
- int is_end = (linep[-intag - keylen + 1] == '-')
- && (linep[-1] == ':')
- && (linep == line + 1 + intag + 1 + 1 + 1 + intag + 1 || linep[-intag - keylen] == '\n');
- if (is_end
- && strncmp(linep - 1 - intag, line + 1, intag))
- {
- pool_debug(pool, SOLV_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%s' %d\n", pd.lineno, linep - 1 - intag, line + 1, intag);
- }
- if (cummulate && !is_end)
+ /* in multi-line value tags (+Key:/-Key:), check for end, cummulate */
+ int is_end = line[intag_linestart] == '-' && linep[-1] == ':' && linep - line == intag_linestart + intag + 2;
+ if (is_end && strncmp(linep - 1 - intag, line + 1, intag))
{
- *linep++ = '\n';
- continue;
+ pool_debug(pool, SOLV_ERROR, "susetags: Nonmatching multi-line tags: %d: '%s' '%.*s'\n", pd.lineno, linep - 1 - intag, intag, line + 1);
}
- if (cummulate && is_end)
+ if (!is_end)
{
- linep[-intag - keylen + 1] = 0;
- if (linep[-intag - keylen] == '\n')
- linep[-intag - keylen] = 0;
- linep = line;
- intag = 0;
+ if (cummulate)
+ {
+ *linep++ = '\n';
+ intag_linestart = linep - line;
+ continue;
+ }
+ intag_linestart = intag + 3;
+ linep = line + intag_linestart;
+ if (!*linep)
+ continue; /* ignore empty lines, bnc#381828 */
}
- if (!cummulate && is_end)
+ else
{
intag = 0;
linep = line;
- continue;
+ if (!cummulate)
+ continue;
+ line[intag_linestart] = 0;
+ if (line[intag_linestart - 1] == '\n')
+ line[intag_linestart - 1] = 0; /* strip trailing newline */
}
- if (!cummulate && !is_end)
- linep = line + intag + keylen;
}
else
linep = line;
- if (!intag && line[0] == '+' && line[1] && line[1] != ':') /* start of +Key:/-Key: tag */
+ /* ignore comments and empty lines */
+ if (!*line || *line == '#')
+ continue;
+
+ /* ignore malformed lines */
+ if (!(line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
+ continue;
+
+ if (!intag && line[0] == '+' && line[1] != ':') /* start of +Key:/-Key: tag */
{
char *tagend = strchr(line, ':');
- if (!tagend)
+ if (!tagend || tagend - line > 100)
{
pd.ret = pool_error(pool, -1, "susetags: line %d: bad line '%s'\n", pd.lineno, line);
break;
}
- intag = tagend - (line + 1);
+ intag = tagend - (line + 1); /* set to tagsize */
cummulate = 0;
- switch (tag_from_string(line)) /* check if accumulation is needed */
+ switch (tag_from_string(line)) /* check if accumulation is needed */
{
case CTAG('+', 'D', 'e', 's'):
case CTAG('+', 'E', 'u', 'l'):
case CTAG('+', 'I', 'n', 's'):
case CTAG('+', 'D', 'e', 'l'):
case CTAG('+', 'A', 'u', 't'):
- if (line[4] == ':' || line[4] == '.')
- cummulate = 1;
+ cummulate = 1;
break;
default:
break;
}
- line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
- line[intag + keylen - 1] = ' ';
- linep = line + intag + keylen;
+ line[0] = '='; /* handle lines between +Key:/-Key: as =Key: */
+ line[intag + 2] = ' ';
+ intag_linestart = intag + 3;
+ linep = line + intag_linestart;
continue;
}
- if (*line == '#' || !*line)
- continue;
- if (! (line[0] && line[1] && line[2] && line[3] && (line[4] == ':' || line[4] == '.')))
- continue;
+
+ /* support language suffix */
+ keylen = 3;
line_lang[0] = 0;
if (line[4] == '.')
{
@@ -667,6 +669,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
line_lang[langsize] = 0;
}
}
+
tag = tag_from_string(line);
if (indelta)
diff --git a/ext/testcase.c b/ext/testcase.c
index 52c139f..a56c4db 100644
--- a/ext/testcase.c
+++ b/ext/testcase.c
@@ -115,6 +115,7 @@ static struct solverflags2str {
{ SOLVER_FLAG_YUM_OBSOLETES, "yumobsoletes", 0 },
{ SOLVER_FLAG_NEED_UPDATEPROVIDE, "needupdateprovide", 0 },
{ SOLVER_FLAG_URPM_REORDER, "urpmreorder", 0 },
+ { SOLVER_FLAG_FOCUS_BEST, "focusbest", 0 },
{ 0, 0, 0 }
};
@@ -767,6 +768,7 @@ testcase_str2solvid(Pool *pool, const char *str)
evrid = pool_strn2id(pool, str + i + 1, repostart - (i + 1), 0);
if (!evrid)
continue;
+ /* first check whatprovides */
FOR_PROVIDES(p, pp, nid)
{
Solvable *s = pool->solvables + p;
@@ -778,6 +780,31 @@ testcase_str2solvid(Pool *pool, const char *str)
continue;
return p;
}
+ /* maybe it's not installable and thus not in whatprovides. do a slow search */
+ if (repo)
+ {
+ Solvable *s;
+ FOR_REPO_SOLVABLES(repo, p, s)
+ {
+ if (s->name != nid || s->evr != evrid)
+ continue;
+ if (arch && s->arch != arch)
+ continue;
+ return p;
+ }
+ }
+ else
+ {
+ FOR_POOL_SOLVABLES(p)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->name != nid || s->evr != evrid)
+ continue;
+ if (arch && s->arch != arch)
+ continue;
+ return p;
+ }
+ }
}
}
return 0;
@@ -2328,7 +2355,7 @@ testcase_write(Solver *solv, const char *dir, int resultflags, const char *testc
Repo *repo = pool_id2repo(pool, repoid);
char *buf = solv_malloc((repo->name ? strlen(repo->name) : 0) + 40);
char *mp;
- orignames[i] = repo->name;
+ orignames[repoid] = repo->name;
if (!repo->name || !repo->name[0])
sprintf(buf, "#%d", repoid);
else
@@ -2353,7 +2380,7 @@ testcase_write(Solver *solv, const char *dir, int resultflags, const char *testc
{
Repo *repo = pool_id2repo(pool, repoid);
solv_free((void *)repo->name);
- repo->name = orignames[i];
+ repo->name = orignames[repoid];
}
solv_free(orignames);
return r;
@@ -2480,6 +2507,7 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
int missing_features = 0;
Id *genid = 0;
int ngenid = 0;
+ Queue autoinstq;
if (!fp && !(fp = fopen(testcase, "r")))
{
@@ -2495,6 +2523,7 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
buf = solv_malloc(bufl);
bufp = buf;
solv = 0;
+ queue_init(&autoinstq);
for (;;)
{
if (bufp - buf + 16 > bufl)
@@ -2849,6 +2878,15 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
}
genid[ngenid++] = id;
}
+ else if (!strcmp(pieces[0], "autoinst") && npieces > 2)
+ {
+ if (strcmp(pieces[1], "name"))
+ {
+ pool_debug(pool, SOLV_ERROR, "testcase_read: autoinst: illegal mode\n");
+ break;
+ }
+ queue_push(&autoinstq, pool_str2id(pool, pieces[2], 1));
+ }
else
{
pool_debug(pool, SOLV_ERROR, "testcase_read: cannot parse command '%s'\n", pieces[0]);
@@ -2856,6 +2894,9 @@ testcase_read(Pool *pool, FILE *fp, const char *testcase, Queue *job, char **res
}
while (job && ngenid > 0)
queue_push2(job, SOLVER_NOOP | SOLVER_SOLVABLE_PROVIDES, genid[--ngenid]);
+ if (autoinstq.count)
+ pool_add_userinstalled_jobs(pool, &autoinstq, job, GET_USERINSTALLED_NAMES | GET_USERINSTALLED_INVERTED);
+ queue_free(&autoinstq);
genid = solv_free(genid);
buf = solv_free(buf);
pieces = solv_free(pieces);
diff --git a/package/libsolv.changes b/package/libsolv.changes
index 7d12812..fd351c3 100644
--- a/package/libsolv.changes
+++ b/package/libsolv.changes
@@ -1,4 +1,14 @@
-------------------------------------------------------------------
+Thu Nov 10 15:09:25 CET 2016 - mls@suse.de
+
+- make testcase_str2solvid work with ignored packages
+- improve checks against corrupt rpm
+- add SOLVER_FLAG_FOCUS_BEST solver flag
+- rework susetags multi-line handling [bnc#1007273]
+- build both for python2 and python3
+- bump version to 0.6.24
+
+-------------------------------------------------------------------
Fri Jul 22 11:37:23 CEST 2016 - mls@suse.de
- also scan /usr/share/metainfo for appdata files [bnc#989830]
diff --git a/package/libsolv.spec.in b/package/libsolv.spec.in
index c2251ec..0009287 100644
--- a/package/libsolv.spec.in
+++ b/package/libsolv.spec.in
@@ -26,6 +26,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build
%bcond_without disable_shared
%bcond_without perl_binding
%bcond_without python_binding
+%bcond_without python3_binding
%bcond_without ruby_binding
%bcond_with zypp
@@ -70,10 +71,14 @@ BuildRequires: ruby-devel
BuildRequires: swig
%endif
%if %{with python_binding}
-%global python_sitearch %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(True);")
+%global python_sitearch %(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))")
BuildRequires: python-devel
BuildRequires: swig
%endif
+%if %{with python3_binding}
+%global python3_sitearch %(python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))")
+BuildRequires: python3-devel
+%endif
Summary: A new approach to package dependency solving
License: BSD-3-Clause
@@ -146,6 +151,13 @@ Group: Development/Languages/Python
%description -n python-solv
Python bindings for sat solver.
+%package -n python3-solv
+Summary: Python3 bindings for the libsolv library
+Group: Development/Languages/Python
+
+%description -n python3-solv
+Python3 bindings for sat solver.
+
%package -n perl-solv
Requires: perl = %{perl_version}
Summary: Perl bindings for the libsolv library
@@ -169,7 +181,7 @@ CMAKE_FLAGS="-DFEDORA=1"
CMAKE_FLAGS="-DSUSE=1 -DENABLE_APPDATA=1 -DENABLE_COMPS=1"
%endif
-cmake $CMAKE_FLAGS \
+cmake $CMAKE_FLAGS \
-DCMAKE_INSTALL_PREFIX=%{_prefix} \
-DLIB=%{_lib} \
-DCMAKE_VERBOSE_MAKEFILE=TRUE \
@@ -178,6 +190,7 @@ cmake $CMAKE_FLAGS \
%{?with_disable_shared:-DDISABLE_SHARED=1} \
%{?with_perl_binding:-DENABLE_PERL=1} \
%{?with_python_binding:-DENABLE_PYTHON=1} \
+ %{?with_python3_binding:-DENABLE_PYTHON3=1} \
%{?with_ruby_binding:-DENABLE_RUBY=1} \
%{?with_zypp:-DENABLE_SUSEREPO=1 -DENABLE_HELIXREPO=1} \
-DUSE_VENDORDIRS=1 \
@@ -186,13 +199,16 @@ make %{?jobs:-j %jobs}
%install
make DESTDIR=$RPM_BUILD_ROOT install
-%if %{with python_binding}
%if 0%{?suse_version}
+%if %{with python_binding}
pushd $RPM_BUILD_ROOT/%{python_sitearch}
python %py_libdir/py_compile.py *.py
python -O %py_libdir/py_compile.py *.py
popd
%endif
+%if %{with python3_binding}
+%py3_compile $RPM_BUILD_ROOT/%{python3_sitearch}
+%endif
%endif
%if %{with disable_shared}
# we want to leave the .a file untouched
@@ -265,4 +281,13 @@ rm -rf "$RPM_BUILD_ROOT"
%{python_sitearch}/*
%endif
+%if %{with python3_binding}
+%files -n python3-solv
+%defattr(-,root,root)
+%{python3_sitearch}/*solv*
+%if 0%{?suse_version}
+%{python3_sitearch}/*/*solv*
+%endif
+%endif
+
%changelog
diff --git a/src/order.c b/src/order.c
index d560865..4fe3e08 100644
--- a/src/order.c
+++ b/src/order.c
@@ -1262,8 +1262,10 @@ transaction_check_order(Transaction *trans)
map_init(&ins, pool->nsolvables);
map_init(&seen, pool->nsolvables);
if (pool->installed)
- FOR_REPO_SOLVABLES(pool->installed, p, s)
- MAPSET(&ins, p);
+ {
+ FOR_REPO_SOLVABLES(pool->installed, p, s)
+ MAPSET(&ins, p);
+ }
lastins = 0;
for (i = 0; i < trans->steps.count; i++)
{
diff --git a/src/problems.c b/src/problems.c
index b57d980..063d47b 100644
--- a/src/problems.c
+++ b/src/problems.c
@@ -588,17 +588,12 @@ create_solutions(Solver *solv, int probnr, int solidx)
{
Pool *pool = solv->pool;
Queue redoq;
- Queue problem, solution, problems_save, branches_save;
+ Queue problem, solution, problems_save, branches_save, decisionq_reason_save;
int i, j, nsol;
int essentialok;
unsigned int now;
int oldmistakes = solv->cleandeps_mistakes ? solv->cleandeps_mistakes->count : 0;
Id extraflags = -1;
- int decisioncnt_update;
- int decisioncnt_keep;
- int decisioncnt_resolve;
- int decisioncnt_weak;
- int decisioncnt_orphan;
now = solv_timems(0);
queue_init(&redoq);
@@ -610,11 +605,6 @@ create_solutions(Solver *solv, int probnr, int solidx)
queue_push(&redoq, solv->decisionq_why.elements[i]);
queue_push(&redoq, solv->decisionmap[p > 0 ? p : -p]);
}
- decisioncnt_update = solv->decisioncnt_update;
- decisioncnt_keep = solv->decisioncnt_keep;
- decisioncnt_resolve = solv->decisioncnt_resolve;
- decisioncnt_weak = solv->decisioncnt_weak;
- decisioncnt_orphan = solv->decisioncnt_orphan;
/* save problems queue */
problems_save = solv->problems;
@@ -624,6 +614,10 @@ create_solutions(Solver *solv, int probnr, int solidx)
branches_save = solv->problems;
memset(&solv->branches, 0, sizeof(solv->branches));
+ /* save decisionq_reason */
+ decisionq_reason_save = solv->decisionq_reason;
+ memset(&solv->decisionq_reason, 0, sizeof(solv->decisionq_reason));
+
/* extract problem from queue */
queue_init(&problem);
for (i = solidx + 1; i < solv->solutions.count; i++)
@@ -711,11 +705,10 @@ create_solutions(Solver *solv, int probnr, int solidx)
solv->decisionmap[p > 0 ? p : -p] = redoq.elements[i + 2];
}
queue_free(&redoq);
- solv->decisioncnt_update = decisioncnt_update;
- solv->decisioncnt_keep = decisioncnt_keep;
- solv->decisioncnt_resolve = decisioncnt_resolve;
- solv->decisioncnt_weak = decisioncnt_weak;
- solv->decisioncnt_orphan = decisioncnt_orphan;
+
+ /* restore decision reasons */
+ queue_free(&solv->decisionq_reason);
+ solv->decisionq_reason = decisionq_reason_save;
/* restore problems */
queue_free(&solv->problems);
@@ -962,8 +955,11 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp,
{
if (*reqrp > 0 && r->p < -1)
{
+ Pool *pool = solv->pool;
Id op = -solv->rules[*reqrp].p;
- if (op > 1 && solv->pool->solvables[op].arch != solv->pool->solvables[-r->p].arch)
+ if (op > 1 && pool->solvables[op].arch != pool->solvables[-r->p].arch &&
+ pool->solvables[op].arch != pool->noarchid &&
+ pool->solvables[-r->p].arch != pool->noarchid)
continue; /* different arch, skip */
}
/* prefer assertions */
diff --git a/src/rules.c b/src/rules.c
index aa90b5f..67f10d8 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -2361,8 +2361,10 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
if (!installed)
break;
if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid))
- FOR_REPO_SOLVABLES(installed, p, s)
- queue_push2(q, DISABLE_UPDATE, p);
+ {
+ FOR_REPO_SOLVABLES(installed, p, s)
+ queue_push2(q, DISABLE_UPDATE, p);
+ }
FOR_JOB_SELECT(p, pp, select, what)
if (pool->solvables[p].repo == installed)
{
@@ -3956,8 +3958,10 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded)
what = job->elements[i + 1];
select = how & SOLVER_SELECTMASK;
if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid))
- FOR_REPO_SOLVABLES(installed, p, s)
- MAPSET(&userinstalled, p - installed->start);
+ {
+ FOR_REPO_SOLVABLES(installed, p, s)
+ MAPSET(&userinstalled, p - installed->start);
+ }
FOR_JOB_SELECT(p, pp, select, what)
if (pool->solvables[p].repo == installed)
MAPSET(&userinstalled, p - installed->start);
diff --git a/src/selection.c b/src/selection.c
index 6b89ab0..37c6184 100644
--- a/src/selection.c
+++ b/src/selection.c
@@ -53,8 +53,10 @@ selection_prune(Pool *pool, Queue *selection)
Solvable *s;
Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- break;
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ break;
+ }
}
else
{
@@ -96,8 +98,10 @@ selection_solvables(Pool *pool, Queue *selection, Queue *pkgs)
Solvable *s;
Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- queue_push(pkgs, p);
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ queue_push(pkgs, p);
+ }
}
else
{
@@ -1100,8 +1104,10 @@ selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
Solvable *s;
Repo *repo = pool_id2repo(pool, sel2->elements[i + 1]);
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- map_set(&m2, p);
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ map_set(&m2, p);
+ }
}
else
{
@@ -1163,13 +1169,15 @@ selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
Solvable *s;
Repo *repo = pool_id2repo(pool, sel1->elements[i + 1]);
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- {
- if (map_tst(&m2, p))
- queue_push(&q1, p);
- else
- miss = 1;
- }
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ {
+ if (map_tst(&m2, p))
+ queue_push(&q1, p);
+ else
+ miss = 1;
+ }
+ }
}
else
{
diff --git a/src/solver.c b/src/solver.c
index 5fca20d..efe3342 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -341,6 +341,7 @@ makeruledecisions(Solver *solv)
assert(solv->decisionq.count == 0);
queue_push(&solv->decisionq, SYSTEMSOLVABLE);
queue_push(&solv->decisionq_why, 0);
+ queue_push2(&solv->decisionq_reason, 0, 0);
solv->decisionmap[SYSTEMSOLVABLE] = 1; /* installed at level '1' */
decisionstart = solv->decisionq.count;
@@ -907,18 +908,7 @@ revert(Solver *solv, int level)
solv->branches.count -= solv->branches.elements[solv->branches.count - 2];
if (solv->recommends_index > solv->decisionq.count)
solv->recommends_index = -1; /* rebuild recommends/suggests maps */
- if (solv->decisionq.count < solv->decisioncnt_jobs)
- solv->decisioncnt_jobs = 0;
- if (solv->decisionq.count < solv->decisioncnt_update)
- solv->decisioncnt_update = 0;
- if (solv->decisionq.count < solv->decisioncnt_keep)
- solv->decisioncnt_keep = 0;
- if (solv->decisionq.count < solv->decisioncnt_resolve)
- solv->decisioncnt_resolve = 0;
- if (solv->decisionq.count < solv->decisioncnt_weak)
- solv->decisioncnt_weak= 0;
- if (solv->decisionq.count < solv->decisioncnt_orphan)
- solv->decisioncnt_orphan = 0;
+ solv->decisionq_reason.count = level + 1;
}
/*-------------------------------------------------------------------
@@ -1111,9 +1101,9 @@ solver_reset(Solver *solv)
}
queue_empty(&solv->decisionq_why);
queue_empty(&solv->decisionq);
+ queue_empty(&solv->decisionq_reason);
solv->recommends_index = -1;
solv->propagate_index = 0;
- solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0;
queue_empty(&solv->branches);
/* adapt learnt rule status to new set of enabled/disabled rules */
@@ -1334,7 +1324,7 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
*/
static int
-setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id ruleid)
+setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id ruleid, Id reason)
{
Pool *pool = solv->pool;
Rule *r, *lr;
@@ -1348,6 +1338,7 @@ setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id rul
solv->decisionmap[-decision] = -level;
queue_push(&solv->decisionq, decision);
queue_push(&solv->decisionq_why, -ruleid); /* <= 0 -> free decision */
+ queue_push(&solv->decisionq_reason, reason);
}
assert(ruleid >= 0 && level > 0);
for (;;)
@@ -1376,7 +1367,7 @@ setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id rul
}
static void
-reorder_dq_for_jobrules(Solver *solv, int level, Queue *dq)
+reorder_dq_for_future_installed(Solver *solv, int level, Queue *dq)
{
Pool *pool = solv->pool;
int i, j, haveone = 0, dqcount = dq->count;
@@ -1464,7 +1455,7 @@ takebranch(Solver *solv, int pos, int end, const char *msg, int disablerules)
{
Pool *pool = solv->pool;
int level;
- Id p, why;
+ Id p, why, reason;
#if 0
{
int i;
@@ -1484,7 +1475,8 @@ takebranch(Solver *solv, int pos, int end, const char *msg, int disablerules)
/* hack: revert simply sets the count, so we can still access the reverted elements */
why = -solv->decisionq_why.elements[solv->decisionq_why.count];
assert(why >= 0);
- return setpropagatelearn(solv, level, p, disablerules, why);
+ reason = solv->decisionq_reason.elements[level + 1];
+ return setpropagatelearn(solv, level, p, disablerules, why, reason);
}
/*-------------------------------------------------------------------
@@ -1499,23 +1491,23 @@ takebranch(Solver *solv, int pos, int end, const char *msg, int disablerules)
*/
static int
-selectandinstall(Solver *solv, int level, Queue *dq, int disablerules, Id ruleid)
+selectandinstall(Solver *solv, int level, Queue *dq, int disablerules, Id ruleid, Id reason)
{
Pool *pool = solv->pool;
Id p;
if (dq->count > 1)
policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
- /* if we're resolving job rules and didn't resolve the installed packages yet,
+ /* if we're resolving rules and didn't resolve the installed packages yet,
* do some special supplements ordering */
- if (dq->count > 1 && ruleid >= solv->jobrules && ruleid < solv->jobrules_end && solv->installed && !solv->focus_installed)
- reorder_dq_for_jobrules(solv, level, dq);
+ if (dq->count > 1 && solv->do_extra_reordering)
+ reorder_dq_for_future_installed(solv, level, dq);
/* if we have multiple candidates we open a branch */
if (dq->count > 1)
createbranch(solv, level, dq, 0, ruleid);
p = dq->elements[0];
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing %s\n", pool_solvid2str(pool, p));
- return setpropagatelearn(solv, level, p, disablerules, ruleid);
+ return setpropagatelearn(solv, level, p, disablerules, ruleid, reason);
}
@@ -1556,6 +1548,7 @@ solver_create(Pool *pool)
queue_init(&solv->ruletojob);
queue_init(&solv->decisionq);
queue_init(&solv->decisionq_why);
+ queue_init(&solv->decisionq_reason);
queue_init(&solv->problems);
queue_init(&solv->orphaned);
queue_init(&solv->learnt_why);
@@ -1581,80 +1574,6 @@ solver_create(Pool *pool)
}
-static int
-resolve_jobrules(Solver *solv, int level, int disablerules, Queue *dq)
-{
- Pool *pool = solv->pool;
- int oldlevel = level;
- int i, olevel;
- Rule *r;
-
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving job rules\n");
- if (!solv->decisioncnt_jobs)
- solv->decisioncnt_jobs = solv->decisionq.count;
- for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++)
- {
- Id l, pp;
- if (r->d < 0) /* ignore disabled rules */
- continue;
- queue_empty(dq);
- FOR_RULELITERALS(l, pp, r)
- {
- if (l < 0)
- {
- if (solv->decisionmap[-l] <= 0)
- break;
- }
- else
- {
- if (solv->decisionmap[l] > 0)
- break;
- if (solv->decisionmap[l] == 0)
- queue_push(dq, l);
- }
- }
- if (l || !dq->count)
- continue;
- /* prune to installed if not updating */
- if (dq->count > 1 && solv->installed && !solv->updatemap_all &&
- !(solv->job.elements[solv->ruletojob.elements[i - solv->jobrules]] & SOLVER_ORUPDATE))
- {
- int j, k;
- for (j = k = 0; j < dq->count; j++)
- {
- Solvable *s = pool->solvables + dq->elements[j];
- if (s->repo == solv->installed)
- {
- dq->elements[k++] = dq->elements[j];
- if (solv->updatemap.size && MAPTST(&solv->updatemap, dq->elements[j] - solv->installed->start))
- {
- k = 0; /* package wants to be updated, do not prune */
- break;
- }
- }
- }
- if (k)
- dq->count = k;
- }
- olevel = level;
- level = selectandinstall(solv, level, dq, disablerules, i);
- if (level <= olevel)
- {
- if (level == olevel)
- {
- i--;
- r--;
- continue; /* try something else */
- }
- if (level < oldlevel)
- return level;
- /* redo from start of jobrules */
- i = solv->jobrules - 1;
- r = solv->rules + i;
- }
- }
- return level;
-}
/*-------------------------------------------------------------------
*
@@ -1687,6 +1606,7 @@ solver_free(Solver *solv)
queue_free(&solv->ruletojob);
queue_free(&solv->decisionq);
queue_free(&solv->decisionq_why);
+ queue_free(&solv->decisionq_reason);
queue_free(&solv->learnt_why);
queue_free(&solv->learnt_pool);
queue_free(&solv->problems);
@@ -1780,6 +1700,8 @@ solver_get_flag(Solver *solv, int flag)
return solv->break_orphans;
case SOLVER_FLAG_FOCUS_INSTALLED:
return solv->focus_installed;
+ case SOLVER_FLAG_FOCUS_BEST:
+ return solv->focus_best;
case SOLVER_FLAG_YUM_OBSOLETES:
return solv->do_yum_obsoletes;
case SOLVER_FLAG_NEED_UPDATEPROVIDE:
@@ -1858,6 +1780,9 @@ solver_set_flag(Solver *solv, int flag, int value)
case SOLVER_FLAG_FOCUS_INSTALLED:
solv->focus_installed = value;
break;
+ case SOLVER_FLAG_FOCUS_BEST:
+ solv->focus_best = value;
+ break;
case SOLVER_FLAG_YUM_OBSOLETES:
solv->do_yum_obsoletes = value;
break;
@@ -1874,6 +1799,79 @@ solver_set_flag(Solver *solv, int flag, int value)
}
static int
+resolve_jobrules(Solver *solv, int level, int disablerules, Queue *dq)
+{
+ Pool *pool = solv->pool;
+ int oldlevel = level;
+ int i, olevel;
+ Rule *r;
+
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving job rules\n");
+ for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++)
+ {
+ Id l, pp;
+ if (r->d < 0) /* ignore disabled rules */
+ continue;
+ queue_empty(dq);
+ FOR_RULELITERALS(l, pp, r)
+ {
+ if (l < 0)
+ {
+ if (solv->decisionmap[-l] <= 0)
+ break;
+ }
+ else
+ {
+ if (solv->decisionmap[l] > 0)
+ break;
+ if (solv->decisionmap[l] == 0)
+ queue_push(dq, l);
+ }
+ }
+ if (l || !dq->count)
+ continue;
+ /* prune to installed if not updating */
+ if (dq->count > 1 && solv->installed && !solv->updatemap_all &&
+ !(solv->job.elements[solv->ruletojob.elements[i - solv->jobrules]] & SOLVER_ORUPDATE))
+ {
+ int j, k;
+ for (j = k = 0; j < dq->count; j++)
+ {
+ Solvable *s = pool->solvables + dq->elements[j];
+ if (s->repo == solv->installed)
+ {
+ dq->elements[k++] = dq->elements[j];
+ if (solv->updatemap.size && MAPTST(&solv->updatemap, dq->elements[j] - solv->installed->start))
+ {
+ k = 0; /* package wants to be updated, do not prune */
+ break;
+ }
+ }
+ }
+ if (k)
+ dq->count = k;
+ }
+ olevel = level;
+ level = selectandinstall(solv, level, dq, disablerules, i, SOLVER_REASON_RESOLVE_JOB);
+ if (level <= olevel)
+ {
+ if (level == olevel)
+ {
+ i--;
+ r--;
+ continue; /* try something else */
+ }
+ if (level < oldlevel)
+ return level;
+ /* redo from start of jobrules */
+ i = solv->jobrules - 1;
+ r = solv->rules + i;
+ }
+ }
+ return level;
+}
+
+static int
cleandeps_check_mistakes(Solver *solv)
{
Pool *pool = solv->pool;
@@ -1941,6 +1939,291 @@ prune_to_update_targets(Solver *solv, Id *cp, Queue *q)
queue_truncate(q, j);
}
+static int
+resolve_installed(Solver *solv, int level, int disablerules, Queue *dq)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ int i, n, pass;
+ int installedpos = solv->installedpos;
+ Solvable *s;
+ Id p, pp;
+ int olevel, origlevel = level;
+
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving installed packages\n");
+ if (!installedpos)
+ installedpos = installed->start;
+ /* we use two passes if we need to update packages
+ * to create a better user experience */
+ for (pass = solv->updatemap.size ? 0 : 1; pass < 2; )
+ {
+ int passlevel = level;
+ Id *specialupdaters = solv->specialupdaters;
+ /* start with installedpos, the position that gave us problems the last time */
+ for (i = installedpos, n = installed->start; n < installed->end; i++, n++)
+ {
+ Rule *r, *rr;
+ Id d;
+
+ if (i == installed->end)
+ i = installed->start;
+ s = pool->solvables + i;
+ if (s->repo != installed)
+ continue;
+
+ if (solv->decisionmap[i] > 0 && (!specialupdaters || !specialupdaters[i - installed->start]))
+ continue; /* already decided */
+ if (!pass && solv->updatemap.size && !MAPTST(&solv->updatemap, i - installed->start))
+ continue; /* updates first */
+ r = solv->rules + solv->updaterules + (i - installed->start);
+ rr = r;
+ if (!rr->p || rr->d < 0) /* disabled -> look at feature rule */
+ rr -= solv->installed->end - solv->installed->start;
+ if (!rr->p) /* identical to update rule? */
+ rr = r;
+ if (!rr->p)
+ continue; /* orpaned package or pseudo package */
+
+ /* check if we should update this package to the latest version
+ * noupdate is set for erase jobs, in that case we want to deinstall
+ * the installed package and not replace it with a newer version
+ * rr->p != i is for dup jobs where the installed package cannot be kept */
+ if (dq->count)
+ queue_empty(dq);
+ if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)) || (rr->p && rr->p != i)))
+ {
+ if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0)
+ {
+ /* special multiversion handling, make sure best version is chosen */
+ if (rr->p == i && solv->decisionmap[i] >= 0)
+ queue_push(dq, i);
+ while ((p = pool->whatprovidesdata[d++]) != 0)
+ if (solv->decisionmap[p] >= 0)
+ queue_push(dq, p);
+ if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start])
+ prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq);
+ if (dq->count)
+ {
+ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
+ p = dq->elements[0];
+ if (p != i && solv->decisionmap[p] == 0)
+ {
+ rr = solv->rules + solv->featurerules + (i - solv->installed->start);
+ if (!rr->p) /* update rule == feature rule? */
+ rr = rr - solv->featurerules + solv->updaterules;
+ dq->count = 1;
+ }
+ else
+ dq->count = 0;
+ }
+ }
+ else
+ {
+ /* update to best package of the update rule */
+ FOR_RULELITERALS(p, pp, rr)
+ {
+ if (solv->decisionmap[p] > 0)
+ {
+ dq->count = 0; /* already fulfilled */
+ break;
+ }
+ if (!solv->decisionmap[p])
+ queue_push(dq, p);
+ }
+ }
+ }
+ if (dq->count && solv->update_targets && solv->update_targets->elements[i - installed->start])
+ prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], dq);
+ /* install best version */
+ if (dq->count)
+ {
+ olevel = level;
+ level = selectandinstall(solv, level, dq, disablerules, rr - solv->rules, SOLVER_REASON_UPDATE_INSTALLED);
+ if (level <= olevel)
+ {
+ if (level < passlevel)
+ break; /* trouble */
+ if (level < olevel)
+ n = installed->start; /* redo all */
+ i--;
+ n--;
+ continue;
+ }
+ }
+ /* if still undecided keep package */
+ if (solv->decisionmap[i] == 0)
+ {
+ olevel = level;
+ if (solv->cleandepsmap.size && MAPTST(&solv->cleandepsmap, i - installed->start))
+ {
+#if 0
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, i));
+ level = setpropagatelearn(solv, level, -i, disablerules, 0, SOLVER_REASON_CLEANDEPS_ERASE);
+#else
+ continue;
+#endif
+ }
+ else
+ {
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "keeping %s\n", pool_solvid2str(pool, i));
+ level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules, SOLVER_REASON_KEEP_INSTALLED);
+ }
+ if (level <= olevel)
+ {
+ if (level < passlevel)
+ break; /* trouble */
+ if (level < olevel)
+ n = installed->start; /* redo all */
+ i--;
+ n--;
+ continue; /* retry with learnt rule */
+ }
+ }
+ }
+ if (n < installed->end)
+ {
+ installedpos = i; /* retry problem solvable next time */
+ if (level < origlevel)
+ break; /* ran into trouble */
+ /* re-run all passes */
+ pass = solv->updatemap.size ? 0 : 1;
+ continue;
+ }
+ /* reset installedpos, advance to next pass */
+ installedpos = installed->start;
+ pass++;
+ }
+ solv->installedpos = installedpos;
+ return level;
+}
+
+static int
+resolve_dependencies(Solver *solv, int level, int disablerules, Queue *dq)
+{
+ Pool *pool = solv->pool;
+ int i, j, n;
+ int postponed;
+ Rule *r;
+ int origlevel = level;
+ Id p, *dp;
+
+ /*
+ * decide
+ */
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "deciding unresolved rules\n");
+ postponed = 0;
+ for (i = 1, n = 1; ; i++, n++)
+ {
+ if (n >= solv->nrules)
+ {
+ if (postponed <= 0)
+ break;
+ i = postponed;
+ postponed = -1;
+ n = 1;
+ }
+ if (i == solv->nrules)
+ i = 1;
+ r = solv->rules + i;
+ if (r->d < 0) /* ignore disabled rules */
+ continue;
+ if (r->p < 0) /* most common cases first */
+ {
+ if (r->d == 0 || solv->decisionmap[-r->p] <= 0)
+ continue;
+ }
+ if (dq->count)
+ queue_empty(dq);
+ if (r->d == 0)
+ {
+ /* binary or unary rule */
+ /* need two positive undecided literals, r->p already checked above */
+ if (r->w2 <= 0)
+ continue;
+ if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
+ continue;
+ queue_push(dq, r->p);
+ queue_push(dq, r->w2);
+ }
+ else
+ {
+ /* make sure that
+ * all negative literals are installed
+ * no positive literal is installed
+ * i.e. the rule is not fulfilled and we
+ * just need to decide on the positive literals
+ * (decisionmap[-r->p] for the r->p < 0 case is already checked above)
+ */
+ if (r->p >= 0)
+ {
+ if (solv->decisionmap[r->p] > 0)
+ continue;
+ if (solv->decisionmap[r->p] == 0)
+ queue_push(dq, r->p);
+ }
+ dp = pool->whatprovidesdata + r->d;
+ while ((p = *dp++) != 0)
+ {
+ if (p < 0)
+ {
+ if (solv->decisionmap[-p] <= 0)
+ break;
+ }
+ else
+ {
+ if (solv->decisionmap[p] > 0)
+ break;
+ if (solv->decisionmap[p] == 0)
+ queue_push(dq, p);
+ }
+ }
+ if (p)
+ continue;
+ }
+ IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
+ {
+ POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "unfulfilled ");
+ solver_printruleclass(solv, SOLV_DEBUG_PROPAGATE, r);
+ }
+ /* dq->count < 2 cannot happen as this means that
+ * the rule is unit */
+ assert(dq->count > 1);
+
+ /* prune to cleandeps packages */
+ if (solv->cleandepsmap.size && solv->installed)
+ {
+ Repo *installed = solv->installed;
+ for (j = 0; j < dq->count; j++)
+ if (pool->solvables[dq->elements[j]].repo == installed && MAPTST(&solv->cleandepsmap, dq->elements[j] - installed->start))
+ break;
+ if (j < dq->count)
+ {
+ dq->elements[0] = dq->elements[j];
+ queue_truncate(dq, 1);
+ }
+ }
+
+ if (dq->count > 1 && postponed >= 0)
+ {
+ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE_NOREORDER);
+ if (dq->count > 1)
+ {
+ if (!postponed)
+ postponed = i;
+ continue;
+ }
+ }
+
+ level = selectandinstall(solv, level, dq, disablerules, r - solv->rules, SOLVER_REASON_RESOLVE);
+ if (level < origlevel)
+ break; /* trouble */
+ /* something changed, so look at all rules again */
+ n = 0;
+ }
+ return level;
+}
+
+
#ifdef ENABLE_COMPLEX_DEPS
static void
@@ -2089,6 +2372,365 @@ prune_disfavored(Solver *solv, Queue *plist)
queue_truncate(plist, j);
}
+static int
+resolve_weak(Solver *solv, int level, int disablerules, Queue *dq, Queue *dqs, int *rerunp)
+{
+ Pool *pool = solv->pool;
+ int i, j, qcount;
+ int olevel;
+ Solvable *s;
+ Map dqmap;
+ int decisioncount;
+ Id p;
+
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended packages\n");
+ if (dq->count)
+ queue_empty(dq); /* recommended packages */
+ if (dqs->count)
+ queue_empty(dqs); /* supplemented packages */
+ for (i = 1; i < pool->nsolvables; i++)
+ {
+ if (solv->decisionmap[i] < 0)
+ continue;
+ s = pool->solvables + i;
+ if (solv->decisionmap[i] > 0)
+ {
+ /* installed, check for recommends */
+ Id *recp, rec, pp, p;
+ if (!solv->addalreadyrecommended && s->repo == solv->installed)
+ continue;
+ /* XXX need to special case AND ? */
+ if (s->recommends)
+ {
+ recp = s->repo->idarraydata + s->recommends;
+ while ((rec = *recp++) != 0)
+ {
+#ifdef ENABLE_COMPLEX_DEPS
+ if (pool_is_complex_dep(pool, rec))
+ {
+ add_complex_recommends(solv, rec, dq, 0);
+ continue;
+ }
+#endif
+ qcount = dq->count;
+ FOR_PROVIDES(p, pp, rec)
+ {
+ if (solv->decisionmap[p] > 0)
+ {
+ dq->count = qcount;
+ break;
+ }
+ else if (solv->decisionmap[p] == 0)
+ {
+ if (solv->dupmap_all && solv->installed && pool->solvables[p].repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))))
+ continue;
+ queue_pushunique(dq, p);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* not yet installed, check if supplemented */
+ if (!s->supplements)
+ continue;
+ if (!pool_installable(pool, s))
+ continue;
+ if (!solver_is_supplementing(solv, s))
+ continue;
+ if (solv->dupmap_all && solv->installed && s->repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, i - solv->installed->start))))
+ continue;
+ if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, i))
+ continue; /* disfavored supplements, do not install */
+ queue_push(dqs, i);
+ }
+ }
+
+ /* filter out disfavored recommended packages */
+ if (dq->count && solv->isdisfavormap.size)
+ prune_disfavored(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)
+ {
+ Map obsmap;
+ Id obs, *obsp, po, ppo;
+
+ map_init(&obsmap, pool->nsolvables);
+ for (p = solv->installed->start; p < solv->installed->end; p++)
+ {
+ s = pool->solvables + p;
+ if (s->repo != solv->installed || !s->obsoletes)
+ continue;
+ if (solv->decisionmap[p] <= 0)
+ continue;
+ if (!solv->keepexplicitobsoletes && solv->multiversion.size && MAPTST(&solv->multiversion, p))
+ continue;
+ obsp = s->repo->idarraydata + s->obsoletes;
+ /* foreach obsoletes */
+ while ((obs = *obsp++) != 0)
+ FOR_PROVIDES(po, ppo, obs)
+ {
+ Solvable *pos = pool->solvables + po;
+ if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pos, obs))
+ continue;
+ if (pool->obsoleteusescolors && !pool_colormatch(pool, s, pos))
+ continue;
+ MAPSET(&obsmap, po);
+ }
+ }
+ for (i = j = 0; i < dqs->count; i++)
+ if (!MAPTST(&obsmap, dqs->elements[i]))
+ dqs->elements[j++] = dqs->elements[i];
+ dqs->count = j;
+ for (i = j = 0; i < dq->count; i++)
+ if (!MAPTST(&obsmap, dq->elements[i]))
+ dq->elements[j++] = dq->elements[i];
+ dq->count = j;
+ map_free(&obsmap);
+ }
+
+ /* filter out all already supplemented packages if requested */
+ if (!solv->addalreadyrecommended && dqs->count)
+ {
+ /* filter out old supplements */
+ for (i = j = 0; i < dqs->count; i++)
+ {
+ p = dqs->elements[i];
+ s = pool->solvables + p;
+ if (s->supplements && solver_is_supplementing_alreadyinstalled(solv, s))
+ dqs->elements[j++] = p;
+ }
+ dqs->count = j;
+ }
+
+ /* multiversion doesn't mix well with supplements.
+ * filter supplemented packages where we already decided
+ * to install a different version (see bnc#501088) */
+ if (dqs->count && solv->multiversion.size)
+ {
+ for (i = j = 0; i < dqs->count; i++)
+ {
+ p = dqs->elements[i];
+ if (MAPTST(&solv->multiversion, p))
+ {
+ Id p2, pp2;
+ s = pool->solvables + p;
+ FOR_PROVIDES(p2, pp2, s->name)
+ if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name)
+ break;
+ if (p2)
+ continue; /* ignore this package */
+ }
+ dqs->elements[j++] = p;
+ }
+ dqs->count = j;
+ }
+
+ /* implicitobsoleteusescolors doesn't mix well with supplements.
+ * filter supplemented packages where we already decided
+ * to install a different architecture */
+ if (dqs->count && pool->implicitobsoleteusescolors)
+ {
+ for (i = j = 0; i < dqs->count; i++)
+ {
+ Id p2, pp2;
+ p = dqs->elements[i];
+ s = pool->solvables + p;
+ FOR_PROVIDES(p2, pp2, s->name)
+ if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name && pool->solvables[p2].arch != s->arch)
+ break;
+ if (p2)
+ continue; /* ignore this package */
+ dqs->elements[j++] = p;
+ }
+ dqs->count = j;
+ }
+
+ /* make dq contain both recommended and supplemented pkgs */
+ if (dqs->count)
+ {
+ for (i = 0; i < dqs->count; i++)
+ queue_pushunique(dq, dqs->elements[i]);
+ }
+
+ if (!dq->count)
+ return level;
+ *rerunp = 1;
+
+ if (dq->count == 1)
+ {
+ /* simple case, just one package. no need to choose to best version */
+ p = dq->elements[0];
+ if (dqs->count)
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
+ else
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
+ return setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
+ }
+
+ /* filter packages, this gives us the best versions */
+ policy_filter_unwanted(solv, dq, POLICY_MODE_RECOMMEND);
+
+ /* create map of result */
+ map_init(&dqmap, pool->nsolvables);
+ for (i = 0; i < dq->count; i++)
+ MAPSET(&dqmap, dq->elements[i]);
+
+ /* prune dqs so that it only contains the best versions */
+ for (i = j = 0; i < dqs->count; i++)
+ {
+ p = dqs->elements[i];
+ if (MAPTST(&dqmap, p))
+ dqs->elements[j++] = p;
+ }
+ dqs->count = j;
+
+ /* install all supplemented packages, but order first */
+ if (dqs->count > 1)
+ policy_filter_unwanted(solv, dqs, POLICY_MODE_SUPPLEMENT);
+ decisioncount = solv->decisionq.count;
+ for (i = 0; i < dqs->count; i++)
+ {
+ p = dqs->elements[i];
+ if (solv->decisionmap[p])
+ continue;
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
+ if (level <= olevel)
+ break;
+ }
+ if (i < dqs->count || solv->decisionq.count < decisioncount)
+ {
+ map_free(&dqmap);
+ return level;
+ }
+
+ /* install all recommended packages */
+ /* more work as we want to created branches if multiple
+ * choices are valid */
+ for (i = 0; i < decisioncount; i++)
+ {
+ Id rec, *recp, pp;
+ p = solv->decisionq.elements[i];
+ if (p < 0)
+ continue;
+ s = pool->solvables + p;
+ if (!s->repo || (!solv->addalreadyrecommended && s->repo == solv->installed))
+ continue;
+ if (!s->recommends)
+ continue;
+ recp = s->repo->idarraydata + s->recommends;
+ while ((rec = *recp++) != 0)
+ {
+ queue_empty(dq);
+#ifdef ENABLE_COMPLEX_DEPS
+ if (pool_is_complex_dep(pool, rec))
+ add_complex_recommends(solv, rec, dq, &dqmap);
+ else
+#endif
+ FOR_PROVIDES(p, pp, rec)
+ {
+ if (solv->decisionmap[p] > 0)
+ {
+ dq->count = 0;
+ break;
+ }
+ else if (solv->decisionmap[p] == 0 && MAPTST(&dqmap, p))
+ queue_push(dq, p);
+ }
+ if (!dq->count)
+ continue;
+ if (dq->count > 1)
+ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
+ /* if we have multiple candidates we open a branch */
+ if (dq->count > 1)
+ createbranch(solv, level, dq, s - pool->solvables, rec);
+ p = dq->elements[0];
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
+ if (level <= olevel || solv->decisionq.count < decisioncount)
+ break; /* we had to revert some decisions */
+ }
+ if (rec)
+ break; /* had a problem above, quit loop */
+ }
+ map_free(&dqmap);
+ return level;
+}
+
+
+static int
+resolve_orphaned(Solver *solv, int level, int disablerules, Queue *dq, int *rerunp)
+{
+ Pool *pool = solv->pool;
+ int i;
+ Id p;
+ int installedone = 0;
+ int olevel;
+
+ /* let's see if we can install some unsupported package */
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "deciding orphaned packages\n");
+ for (i = 0; i < solv->orphaned.count; i++)
+ {
+ p = solv->orphaned.elements[i];
+ if (solv->decisionmap[p])
+ continue; /* already decided */
+ if (solv->droporphanedmap_all)
+ continue;
+ if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))
+ continue;
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "keeping orphaned %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_RESOLVE_ORPHAN);
+ installedone = 1;
+ if (level < olevel)
+ break;
+ }
+ if (installedone || i < solv->orphaned.count)
+ {
+ *rerunp = 1;
+ return level;
+ }
+ for (i = 0; i < solv->orphaned.count; i++)
+ {
+ p = solv->orphaned.elements[i];
+ if (solv->decisionmap[p])
+ continue; /* already decided */
+ POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing orphaned %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_RESOLVE_ORPHAN);
+ if (level < olevel)
+ {
+ *rerunp = 1;
+ return level;
+ }
+ }
+ if (solv->brokenorphanrules)
+ {
+ solver_check_brokenorphanrules(solv, dq);
+ if (dq->count)
+ {
+ policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE);
+ for (i = 0; i < dq->count; i++)
+ {
+ p = dq->elements[i];
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "installing orphaned dep %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_RESOLVE_ORPHAN);
+ if (level < olevel)
+ break;
+ }
+ *rerunp = 1;
+ }
+ }
+ return level;
+}
+
/*-------------------------------------------------------------------
*
* solver_run_sat
@@ -2105,12 +2747,11 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
int systemlevel;
int level, olevel;
Rule *r;
- int i, j, n;
+ int i;
Solvable *s;
Pool *pool = solv->pool;
- Id p, pp, *dp, postponed;
+ Id p;
int minimizationsteps;
- int installedpos = solv->installed ? solv->installed->start : 0;
IF_POOLDEBUG (SOLV_DEBUG_RULE_CREATION)
{
@@ -2126,6 +2767,8 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
queue_init(&dq);
queue_init(&dqs);
+ solv->installedpos = 0;
+ solv->do_extra_reordering = 0;
/*
* here's the main loop:
@@ -2170,167 +2813,41 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
*/
if (level < systemlevel && !solv->focus_installed)
{
+ if (solv->installed && solv->installed->nsolvables && !solv->installed->disabled)
+ solv->do_extra_reordering = 1;
olevel = level;
level = resolve_jobrules(solv, level, disablerules, &dq);
+ solv->do_extra_reordering = 0;
if (level < olevel)
continue;
systemlevel = level + 1;
}
+ /* resolve job dependencies in the focus_best case */
+ if (level < systemlevel && solv->focus_best && !solv->focus_installed && solv->installed && solv->installed->nsolvables && !solv->installed->disabled)
+ {
+ solv->do_extra_reordering = 1;
+ olevel = level;
+ level = resolve_dependencies(solv, level, disablerules, &dq);
+ solv->do_extra_reordering = 0;
+ if (level < olevel)
+ continue; /* start over */
+ systemlevel = level + 1;
+ }
/*
* installed packages
*/
- if (!solv->decisioncnt_update)
- solv->decisioncnt_update = solv->decisionq.count;
if (level < systemlevel && solv->installed && solv->installed->nsolvables && !solv->installed->disabled)
{
- Repo *installed = solv->installed;
- int pass;
-
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving installed packages\n");
- /* we use two passes if we need to update packages
- * to create a better user experience */
- for (pass = solv->updatemap.size ? 0 : 1; pass < 2; pass++)
- {
- int passlevel = level;
- Id *specialupdaters = solv->specialupdaters;
- if (pass == 1 && !solv->decisioncnt_keep)
- solv->decisioncnt_keep = solv->decisionq.count;
- /* start with installedpos, the position that gave us problems the last time */
- for (i = installedpos, n = installed->start; n < installed->end; i++, n++)
- {
- Rule *rr;
- Id d;
-
- if (i == installed->end)
- i = installed->start;
- s = pool->solvables + i;
- if (s->repo != installed)
- continue;
-
- if (solv->decisionmap[i] > 0 && (!specialupdaters || !specialupdaters[i - installed->start]))
- continue; /* already decided */
- if (!pass && solv->updatemap.size && !MAPTST(&solv->updatemap, i - installed->start))
- continue; /* updates first */
- r = solv->rules + solv->updaterules + (i - installed->start);
- rr = r;
- if (!rr->p || rr->d < 0) /* disabled -> look at feature rule */
- rr -= solv->installed->end - solv->installed->start;
- if (!rr->p) /* identical to update rule? */
- rr = r;
- if (!rr->p)
- continue; /* orpaned package or pseudo package */
-
- /* check if we should update this package to the latest version
- * noupdate is set for erase jobs, in that case we want to deinstall
- * the installed package and not replace it with a newer version
- * rr->p != i is for dup jobs where the installed package cannot be kept */
- queue_empty(&dq);
- if (!MAPTST(&solv->noupdate, i - installed->start) && (solv->decisionmap[i] < 0 || solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, i - installed->start)) || (rr->p && rr->p != i)))
- {
- if (specialupdaters && (d = specialupdaters[i - installed->start]) != 0)
- {
- /* special multiversion handling, make sure best version is chosen */
- if (rr->p == i && solv->decisionmap[i] >= 0)
- queue_push(&dq, i);
- while ((p = pool->whatprovidesdata[d++]) != 0)
- if (solv->decisionmap[p] >= 0)
- queue_push(&dq, p);
- if (dq.count && solv->update_targets && solv->update_targets->elements[i - installed->start])
- prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], &dq);
- if (dq.count)
- {
- policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
- p = dq.elements[0];
- if (p != i && solv->decisionmap[p] == 0)
- {
- rr = solv->rules + solv->featurerules + (i - solv->installed->start);
- if (!rr->p) /* update rule == feature rule? */
- rr = rr - solv->featurerules + solv->updaterules;
- dq.count = 1;
- }
- else
- dq.count = 0;
- }
- }
- else
- {
- /* update to best package of the update rule */
- FOR_RULELITERALS(p, pp, rr)
- {
- if (solv->decisionmap[p] > 0)
- {
- dq.count = 0; /* already fulfilled */
- break;
- }
- if (!solv->decisionmap[p])
- queue_push(&dq, p);
- }
- }
- }
- if (dq.count && solv->update_targets && solv->update_targets->elements[i - installed->start])
- prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], &dq);
- /* install best version */
- if (dq.count)
- {
- olevel = level;
- level = selectandinstall(solv, level, &dq, disablerules, rr - solv->rules);
- if (level <= olevel)
- {
- if (level < passlevel)
- break; /* trouble */
- if (level < olevel)
- n = installed->start; /* redo all */
- i--;
- n--;
- continue;
- }
- }
- /* if still undecided keep package */
- if (solv->decisionmap[i] == 0)
- {
- olevel = level;
- if (solv->cleandepsmap.size && MAPTST(&solv->cleandepsmap, i - installed->start))
- {
-#if 0
- POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, i));
- level = setpropagatelearn(solv, level, -i, disablerules, 0);
-#else
- continue;
-#endif
- }
- else
- {
- POOL_DEBUG(SOLV_DEBUG_POLICY, "keeping %s\n", pool_solvid2str(pool, i));
- level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules);
- }
- if (level <= olevel)
- {
- if (level < passlevel)
- break; /* trouble */
- if (level < olevel)
- n = installed->start; /* redo all */
- i--;
- n--;
- continue; /* retry with learnt rule */
- }
- }
- }
- if (n < installed->end)
- {
- installedpos = i; /* retry problem solvable next time */
- break; /* ran into trouble */
- }
- installedpos = installed->start; /* reset installedpos */
- }
+ olevel = level;
+ level = resolve_installed(solv, level, disablerules, &dq);
+ if (level < olevel)
+ continue;
systemlevel = level + 1;
- if (pass < 2)
- continue; /* had trouble, retry */
}
- if (!solv->decisioncnt_keep)
- solv->decisioncnt_keep = solv->decisionq.count;
+ /* resolve jobs in focus_installed case */
if (level < systemlevel && solv->focus_installed)
{
olevel = level;
@@ -2343,494 +2860,51 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
if (level < systemlevel)
systemlevel = level;
- /*
- * decide
- */
- if (!solv->decisioncnt_resolve)
- solv->decisioncnt_resolve = solv->decisionq.count;
- POOL_DEBUG(SOLV_DEBUG_POLICY, "deciding unresolved rules\n");
- postponed = 0;
- for (i = 1, n = 1; ; i++, n++)
- {
- if (n >= solv->nrules)
- {
- if (postponed <= 0)
- break;
- i = postponed;
- postponed = -1;
- n = 1;
- }
- if (i == solv->nrules)
- i = 1;
- r = solv->rules + i;
- if (r->d < 0) /* ignore disabled rules */
- continue;
- if (r->p < 0) /* most common cases first */
- {
- if (r->d == 0 || solv->decisionmap[-r->p] <= 0)
- continue;
- }
- if (dq.count)
- queue_empty(&dq);
- if (r->d == 0)
- {
- /* binary or unary rule */
- /* need two positive undecided literals, r->p already checked above */
- if (r->w2 <= 0)
- continue;
- if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
- continue;
- queue_push(&dq, r->p);
- queue_push(&dq, r->w2);
- }
- else
- {
- /* make sure that
- * all negative literals are installed
- * no positive literal is installed
- * i.e. the rule is not fulfilled and we
- * just need to decide on the positive literals
- * (decisionmap[-r->p] for the r->p < 0 case is already checked above)
- */
- if (r->p >= 0)
- {
- if (solv->decisionmap[r->p] > 0)
- continue;
- if (solv->decisionmap[r->p] == 0)
- queue_push(&dq, r->p);
- }
- dp = pool->whatprovidesdata + r->d;
- while ((p = *dp++) != 0)
- {
- if (p < 0)
- {
- if (solv->decisionmap[-p] <= 0)
- break;
- }
- else
- {
- if (solv->decisionmap[p] > 0)
- break;
- if (solv->decisionmap[p] == 0)
- queue_push(&dq, p);
- }
- }
- if (p)
- continue;
- }
- IF_POOLDEBUG (SOLV_DEBUG_PROPAGATE)
- {
- POOL_DEBUG(SOLV_DEBUG_PROPAGATE, "unfulfilled ");
- solver_printruleclass(solv, SOLV_DEBUG_PROPAGATE, r);
- }
- /* dq.count < 2 cannot happen as this means that
- * the rule is unit */
- assert(dq.count > 1);
-
- /* prune to cleandeps packages */
- if (solv->cleandepsmap.size && solv->installed)
- {
- Repo *installed = solv->installed;
- for (j = 0; j < dq.count; j++)
- if (pool->solvables[dq.elements[j]].repo == installed && MAPTST(&solv->cleandepsmap, dq.elements[j] - installed->start))
- break;
- if (j < dq.count)
- {
- dq.elements[0] = dq.elements[j];
- queue_truncate(&dq, 1);
- }
- }
-
- if (dq.count > 1 && postponed >= 0)
- {
- policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE_NOREORDER);
- if (dq.count > 1)
- {
- if (!postponed)
- postponed = i;
- continue;
- }
- }
-
- olevel = level;
- level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules);
- if (level < systemlevel)
- break; /* trouble */
- /* something changed, so look at all rules again */
- n = 0;
- }
-
- if (n < solv->nrules) /* ran into trouble? */
+ /* resolve all dependencies */
+ olevel = level;
+ level = resolve_dependencies(solv, level, disablerules, &dq);
+ if (level < olevel)
continue; /* start over */
/* decide leftover cleandeps packages */
if (solv->cleandepsmap.size && solv->installed)
- {
- for (p = solv->installed->start; p < solv->installed->end; p++)
- {
- s = pool->solvables + p;
- if (s->repo != solv->installed)
- continue;
- if (solv->decisionmap[p] == 0 && MAPTST(&solv->cleandepsmap, p - solv->installed->start))
- {
- POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, p));
- olevel = level;
- level = setpropagatelearn(solv, level, -p, 0, 0);
- if (level < olevel)
- break;
- }
- }
- if (p < solv->installed->end)
- continue;
- }
+ {
+ for (p = solv->installed->start; p < solv->installed->end; p++)
+ {
+ s = pool->solvables + p;
+ if (s->repo != solv->installed)
+ continue;
+ if (solv->decisionmap[p] == 0 && MAPTST(&solv->cleandepsmap, p - solv->installed->start))
+ {
+ POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, p));
+ olevel = level;
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_CLEANDEPS_ERASE);
+ if (level < olevel)
+ break;
+ }
+ }
+ if (p < solv->installed->end)
+ continue;
+ }
/* at this point we have a consistent system. now do the extras... */
- if (!solv->decisioncnt_weak)
- solv->decisioncnt_weak = solv->decisionq.count;
if (doweak)
{
- int qcount;
-
- POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended packages\n");
- queue_empty(&dq); /* recommended packages */
- queue_empty(&dqs); /* supplemented packages */
- for (i = 1; i < pool->nsolvables; i++)
- {
- if (solv->decisionmap[i] < 0)
- continue;
- if (solv->decisionmap[i] > 0)
- {
- /* installed, check for recommends */
- Id *recp, rec, pp, p;
- s = pool->solvables + i;
- if (!solv->addalreadyrecommended && s->repo == solv->installed)
- continue;
- /* XXX need to special case AND ? */
- if (s->recommends)
- {
- recp = s->repo->idarraydata + s->recommends;
- while ((rec = *recp++) != 0)
- {
-#ifdef ENABLE_COMPLEX_DEPS
- if (pool_is_complex_dep(pool, rec))
- {
- add_complex_recommends(solv, rec, &dq, 0);
- continue;
- }
-#endif
- qcount = dq.count;
- FOR_PROVIDES(p, pp, rec)
- {
- if (solv->decisionmap[p] > 0)
- {
- dq.count = qcount;
- break;
- }
- else if (solv->decisionmap[p] == 0)
- {
- if (solv->dupmap_all && solv->installed && pool->solvables[p].repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))))
- continue;
- queue_pushunique(&dq, p);
- }
- }
- }
- }
- }
- else
- {
- s = pool->solvables + i;
- if (!s->supplements)
- continue;
- if (!pool_installable(pool, s))
- continue;
- if (!solver_is_supplementing(solv, s))
- continue;
- if (solv->dupmap_all && solv->installed && s->repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, i - solv->installed->start))))
- continue;
- if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, i))
- continue; /* disfavored supplements, do not install */
- queue_push(&dqs, i);
- }
- }
-
- /* filter out disfavored recommended packages */
- if (dq.count && solv->isdisfavormap.size)
- prune_disfavored(solv, &dq);
-
- /* filter out all packages obsoleted by installed packages */
- /* this is no longer needed if we have reverse obsoletes */
- if ((dqs.count || dq.count) && solv->installed)
- {
- Map obsmap;
- Id obs, *obsp, po, ppo;
-
- map_init(&obsmap, pool->nsolvables);
- for (p = solv->installed->start; p < solv->installed->end; p++)
- {
- s = pool->solvables + p;
- if (s->repo != solv->installed || !s->obsoletes)
- continue;
- if (solv->decisionmap[p] <= 0)
- continue;
- if (!solv->keepexplicitobsoletes && solv->multiversion.size && MAPTST(&solv->multiversion, p))
- continue;
- obsp = s->repo->idarraydata + s->obsoletes;
- /* foreach obsoletes */
- while ((obs = *obsp++) != 0)
- FOR_PROVIDES(po, ppo, obs)
- {
- Solvable *pos = pool->solvables + po;
- if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pos, obs))
- continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, pos))
- continue;
- MAPSET(&obsmap, po);
- }
- }
- for (i = j = 0; i < dqs.count; i++)
- if (!MAPTST(&obsmap, dqs.elements[i]))
- dqs.elements[j++] = dqs.elements[i];
- dqs.count = j;
- for (i = j = 0; i < dq.count; i++)
- if (!MAPTST(&obsmap, dq.elements[i]))
- dq.elements[j++] = dq.elements[i];
- dq.count = j;
- map_free(&obsmap);
- }
-
- /* filter out all already supplemented packages if requested */
- if (!solv->addalreadyrecommended && dqs.count)
- {
- /* filter out old supplements */
- for (i = j = 0; i < dqs.count; i++)
- {
- p = dqs.elements[i];
- s = pool->solvables + p;
- if (s->supplements && solver_is_supplementing_alreadyinstalled(solv, s))
- dqs.elements[j++] = p;
- }
- dqs.count = j;
- }
-
- /* multiversion doesn't mix well with supplements.
- * filter supplemented packages where we already decided
- * to install a different version (see bnc#501088) */
- if (dqs.count && solv->multiversion.size)
- {
- for (i = j = 0; i < dqs.count; i++)
- {
- p = dqs.elements[i];
- if (MAPTST(&solv->multiversion, p))
- {
- Id p2, pp2;
- s = pool->solvables + p;
- FOR_PROVIDES(p2, pp2, s->name)
- if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name)
- break;
- if (p2)
- continue; /* ignore this package */
- }
- dqs.elements[j++] = p;
- }
- dqs.count = j;
- }
-
- /* implicitobsoleteusescolors doesn't mix well with supplements.
- * filter supplemented packages where we already decided
- * to install a different architecture */
- if (dqs.count && pool->implicitobsoleteusescolors)
- {
- for (i = j = 0; i < dqs.count; i++)
- {
- Id p2, pp2;
- p = dqs.elements[i];
- s = pool->solvables + p;
- FOR_PROVIDES(p2, pp2, s->name)
- if (solv->decisionmap[p2] > 0 && pool->solvables[p2].name == s->name && pool->solvables[p2].arch != s->arch)
- break;
- if (p2)
- continue; /* ignore this package */
- dqs.elements[j++] = p;
- }
- dqs.count = j;
- }
-
- /* make dq contain both recommended and supplemented pkgs */
- if (dqs.count)
- {
- for (i = 0; i < dqs.count; i++)
- queue_pushunique(&dq, dqs.elements[i]);
- }
-
- if (dq.count)
- {
- Map dqmap;
- int decisioncount = solv->decisionq.count;
-
- if (dq.count == 1)
- {
- /* simple case, just one package. no need to choose to best version */
- p = dq.elements[0];
- if (dqs.count)
- POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
- else
- POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
- level = setpropagatelearn(solv, level, p, 0, 0);
- continue; /* back to main loop */
- }
-
- /* filter packages, this gives us the best versions */
- policy_filter_unwanted(solv, &dq, POLICY_MODE_RECOMMEND);
-
- /* create map of result */
- map_init(&dqmap, pool->nsolvables);
- for (i = 0; i < dq.count; i++)
- MAPSET(&dqmap, dq.elements[i]);
-
- /* prune dqs so that it only contains the best versions */
- for (i = j = 0; i < dqs.count; i++)
- {
- p = dqs.elements[i];
- if (MAPTST(&dqmap, p))
- dqs.elements[j++] = p;
- }
- dqs.count = j;
-
- /* install all supplemented packages, but order first */
- if (dqs.count > 1)
- policy_filter_unwanted(solv, &dqs, POLICY_MODE_SUPPLEMENT);
- for (i = 0; i < dqs.count; i++)
- {
- p = dqs.elements[i];
- if (solv->decisionmap[p])
- continue;
- POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
- olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
- if (level <= olevel)
- break;
- }
- if (i < dqs.count || solv->decisionq.count < decisioncount)
- {
- map_free(&dqmap);
- continue;
- }
-
- /* install all recommended packages */
- /* more work as we want to created branches if multiple
- * choices are valid */
- for (i = 0; i < decisioncount; i++)
- {
- Id rec, *recp, pp;
- p = solv->decisionq.elements[i];
- if (p < 0)
- continue;
- s = pool->solvables + p;
- if (!s->repo || (!solv->addalreadyrecommended && s->repo == solv->installed))
- continue;
- if (!s->recommends)
- continue;
- recp = s->repo->idarraydata + s->recommends;
- while ((rec = *recp++) != 0)
- {
- queue_empty(&dq);
-#ifdef ENABLE_COMPLEX_DEPS
- if (pool_is_complex_dep(pool, rec))
- add_complex_recommends(solv, rec, &dq, &dqmap);
- else
-#endif
- FOR_PROVIDES(p, pp, rec)
- {
- if (solv->decisionmap[p] > 0)
- {
- dq.count = 0;
- break;
- }
- else if (solv->decisionmap[p] == 0 && MAPTST(&dqmap, p))
- queue_push(&dq, p);
- }
- if (!dq.count)
- continue;
- if (dq.count > 1)
- policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
- /* if we have multiple candidates we open a branch */
- if (dq.count > 1)
- createbranch(solv, level, &dq, s - pool->solvables, rec);
- p = dq.elements[0];
- POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
- olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
- if (level <= olevel || solv->decisionq.count < decisioncount)
- break; /* we had to revert some decisions */
- }
- if (rec)
- break; /* had a problem above, quit loop */
- }
- map_free(&dqmap);
- continue; /* back to main loop so that all deps are checked */
- }
+ int rerun = 0;
+ level = resolve_weak(solv, level, disablerules, &dq, &dqs, &rerun);
+ if (rerun)
+ continue;
}
- if (!solv->decisioncnt_orphan)
- solv->decisioncnt_orphan = solv->decisionq.count;
if (solv->installed && (solv->orphaned.count || solv->brokenorphanrules))
{
- int installedone = 0;
-
- /* let's see if we can install some unsupported package */
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "deciding orphaned packages\n");
- for (i = 0; i < solv->orphaned.count; i++)
- {
- p = solv->orphaned.elements[i];
- if (solv->decisionmap[p])
- continue; /* already decided */
- if (solv->droporphanedmap_all)
- continue;
- if (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, p - solv->installed->start))
- continue;
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "keeping orphaned %s\n", pool_solvid2str(pool, p));
- olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
- installedone = 1;
- if (level < olevel)
- break;
- }
- if (installedone || i < solv->orphaned.count)
- continue; /* back to main loop */
- for (i = 0; i < solv->orphaned.count; i++)
- {
- p = solv->orphaned.elements[i];
- if (solv->decisionmap[p])
- continue; /* already decided */
- POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing orphaned %s\n", pool_solvid2str(pool, p));
- olevel = level;
- level = setpropagatelearn(solv, level, -p, 0, 0);
- if (level < olevel)
- break;
- }
- if (i < solv->orphaned.count)
- continue; /* back to main loop */
- if (solv->brokenorphanrules)
- {
- solver_check_brokenorphanrules(solv, &dq);
- if (dq.count)
- {
- policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE);
- for (i = 0; i < dq.count; i++)
- {
- p = dq.elements[i];
- POOL_DEBUG(SOLV_DEBUG_POLICY, "installing orphaned dep %s\n", pool_solvid2str(pool, p));
- olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
- if (level < olevel)
- break;
- }
- continue;
- }
- }
+ int rerun = 0;
+ level = resolve_orphaned(solv, level, disablerules, &dq, &rerun);
+ if (rerun)
+ continue;
}
-
+
/* one final pass to make sure we decided all installed packages */
if (solv->installed)
{
@@ -2843,7 +2917,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
continue;
POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing unwanted %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, -p, 0, 0);
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_CLEANDEPS_ERASE);
if (level < olevel)
break;
}
@@ -2950,22 +3024,13 @@ solver_run_sat(Solver *solv, int disablerules, int doweak)
/* no minimization found, we're finally finished! */
break;
}
+ assert(level == -1 || level + 1 == solv->decisionq_reason.count);
POOL_DEBUG(SOLV_DEBUG_STATS, "solver statistics: %d learned rules, %d unsolvable, %d minimization steps\n", solv->stats_learned, solv->stats_unsolvable, minimizationsteps);
POOL_DEBUG(SOLV_DEBUG_STATS, "done solving.\n\n");
queue_free(&dq);
queue_free(&dqs);
- if (level < 0)
- {
- /* unsolvable */
- solv->decisioncnt_jobs = solv->decisionq.count;
- solv->decisioncnt_update = solv->decisionq.count;
- solv->decisioncnt_keep = solv->decisionq.count;
- solv->decisioncnt_resolve = solv->decisionq.count;
- solv->decisioncnt_weak = solv->decisionq.count;
- solv->decisioncnt_orphan = solv->decisionq.count;
- }
#if 0
solver_printdecisionq(solv, SOLV_DEBUG_RESULT);
#endif
@@ -3141,8 +3206,10 @@ solver_calculate_multiversionmap(Pool *pool, Queue *job, Map *multiversionmap)
Solvable *s;
Repo *repo = pool_id2repo(pool, what);
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- MAPSET(multiversionmap, p);
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ MAPSET(multiversionmap, p);
+ }
}
FOR_JOB_SELECT(p, pp, select, what)
MAPSET(multiversionmap, p);
@@ -3513,7 +3580,7 @@ solver_solve(Solver *solv, Queue *job)
memset(solv->decisionmap, 0, pool->nsolvables * sizeof(Id));
queue_empty(&solv->decisionq);
queue_empty(&solv->decisionq_why);
- solv->decisioncnt_jobs = solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0;
+ queue_empty(&solv->decisionq_reason);
queue_empty(&solv->learnt_why);
queue_empty(&solv->learnt_pool);
queue_empty(&solv->branches);
@@ -3947,8 +4014,10 @@ solver_solve(Solver *solv, Queue *job)
{
Repo *repo = pool_id2repo(pool, what);
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- solver_addjobrule(solv, -p, 0, 0, i, weak);
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ solver_addjobrule(solv, -p, 0, 0, i, weak);
+ }
}
#ifdef ENABLE_COMPLEX_DEPS
else if ((select == SOLVER_SOLVABLE_PROVIDES || select == SOLVER_SOLVABLE_NAME) && pool_is_complex_dep(pool, what))
@@ -4023,8 +4092,10 @@ solver_solve(Solver *solv, Queue *job)
{
Repo *repo = pool_id2repo(pool, what);
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
+ }
}
FOR_JOB_SELECT(p, pp, select, what)
solver_addjobrule(solv, installed && pool->solvables[p].repo == installed ? p : -p, 0, 0, i, weak);
@@ -4284,20 +4355,12 @@ void solver_get_recommendations(Solver *solv, Queue *recommendationsq, Queue *su
MAPZERO(&solv->recommendsmap);
/* put all packages the solver already chose in the map */
- if (solv->decisioncnt_weak)
- {
- for (i = solv->decisioncnt_weak; i < solv->decisioncnt_orphan; i++)
- {
- Id why;
- why = solv->decisionq_why.elements[i];
- if (why)
- continue; /* forced by unit rule or dep resolving */
- p = solv->decisionq.elements[i];
- if (p < 0)
- continue;
+ for (i = 1; i < solv->decisionq.count; i++)
+ if ((p = solv->decisionq.elements[i]) > 0 && solv->decisionq_why.elements[i] == 0)
+ {
+ if (solv->decisionq_reason.elements[solv->decisionmap[p]] == SOLVER_REASON_WEAKDEP)
MAPSET(&solv->recommendsmap, p);
- }
- }
+ }
for (i = 0; i < solv->decisionq.count; i++)
{
@@ -4565,36 +4628,8 @@ solver_describe_decision(Solver *solv, Id p, Id *infop)
*infop = why > 0 ? why : -why;
if (why > 0)
return SOLVER_REASON_UNIT_RULE;
- why = -why;
- if (i == 0)
- return SOLVER_REASON_KEEP_INSTALLED; /* the systemsolvable */
- if (i < solv->decisioncnt_update)
- return SOLVER_REASON_RESOLVE_JOB;
- if (i < solv->decisioncnt_keep)
- {
- if (why == 0 && pp < 0)
- return SOLVER_REASON_CLEANDEPS_ERASE;
- return SOLVER_REASON_UPDATE_INSTALLED;
- }
- if (i < solv->decisioncnt_resolve)
- {
- if (solv->focus_installed && i >= solv->decisioncnt_jobs)
- return SOLVER_REASON_RESOLVE_JOB;
- if (why == 0 && pp < 0)
- return SOLVER_REASON_CLEANDEPS_ERASE;
- return SOLVER_REASON_KEEP_INSTALLED;
- }
- if (i < solv->decisioncnt_weak)
- {
- if (why == 0 && pp < 0)
- return SOLVER_REASON_CLEANDEPS_ERASE;
- }
- if (why > 0)
- return SOLVER_REASON_RESOLVE;
- /* weak or orphaned */
- if (i < solv->decisioncnt_orphan)
- return SOLVER_REASON_WEAKDEP;
- return SOLVER_REASON_RESOLVE_ORPHAN;
+ i = solv->decisionmap[p] >= 0 ? solv->decisionmap[p] : -solv->decisionmap[p];
+ return solv->decisionq_reason.elements[i];
}
@@ -4615,7 +4650,8 @@ solver_describe_weakdep_decision(Solver *solv, Id p, Queue *whyq)
break;
if (decisionno == solv->decisionq.count)
return; /* huh? */
- if (decisionno < solv->decisioncnt_weak || decisionno >= solv->decisioncnt_orphan)
+ i = solv->decisionmap[p] >= 0 ? solv->decisionmap[p] : -solv->decisionmap[p];
+ if (solv->decisionq_reason.elements[i] != SOLVER_REASON_WEAKDEP)
return; /* huh? */
/* 1) list all packages that recommend us */
@@ -4716,8 +4752,10 @@ pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what)
Repo *repo = pool_id2repo(pool, what);
Solvable *s;
if (repo)
- FOR_REPO_SOLVABLES(repo, p, s)
- queue_push(pkgs, p);
+ {
+ FOR_REPO_SOLVABLES(repo, p, s)
+ queue_push(pkgs, p);
+ }
}
else
{
@@ -4873,8 +4911,10 @@ solver_get_userinstalled(Solver *solv, Queue *q, int flags)
what = solv->job.elements[i + 1];
select = how & SOLVER_SELECTMASK;
if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid))
- FOR_REPO_SOLVABLES(installed, p, s)
- MAPSET(&userinstalled, p - installed->start);
+ {
+ FOR_REPO_SOLVABLES(installed, p, s)
+ MAPSET(&userinstalled, p - installed->start);
+ }
FOR_JOB_SELECT(p, pp, select, what)
if (pool->solvables[p].repo == installed)
MAPSET(&userinstalled, p - installed->start);
diff --git a/src/solver.h b/src/solver.h
index 758f1eb..be240c9 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -107,19 +107,13 @@ struct _Solver {
/* our decisions: */
Queue decisionq; /* >0:install, <0:remove/conflict */
Queue decisionq_why; /* index of rule, Offset into rules */
+ Queue decisionq_reason; /* reason for decision, indexed by level */
Id *decisionmap; /* map for all available solvables,
* = 0: undecided
* > 0: level of decision when installed,
* < 0: level of decision when conflict */
- int decisioncnt_jobs;
- int decisioncnt_update;
- int decisioncnt_keep;
- int decisioncnt_resolve;
- int decisioncnt_weak;
- int decisioncnt_orphan;
-
/* learnt rule history */
Queue learnt_why;
Queue learnt_pool;
@@ -166,6 +160,7 @@ struct _Solver {
int bestobeypolicy; /* true: stay in policy with the best rules */
int noautotarget; /* true: do not assume targeted for up/dup jobs that contain no installed solvable */
int focus_installed; /* true: resolve update rules first */
+ int focus_best; /* true: resolve job dependencies first */
int do_yum_obsoletes; /* true: add special yumobs rules */
int urpmreorder; /* true: do special urpm package reordering */
@@ -203,6 +198,9 @@ struct _Solver {
Queue *favorq;
Map favormap; /* favored / disfavored packages */
Map isdisfavormap;
+
+ int installedpos; /* for resolve_installed */
+ int do_extra_reordering; /* reorder for future installed packages */
#endif /* LIBSOLV_INTERNAL */
};
@@ -309,6 +307,7 @@ typedef struct _Solver Solver;
#define SOLVER_FLAG_YUM_OBSOLETES 21
#define SOLVER_FLAG_NEED_UPDATEPROVIDE 22
#define SOLVER_FLAG_URPM_REORDER 23
+#define SOLVER_FLAG_FOCUS_BEST 24
#define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead of ids */
#define GET_USERINSTALLED_INVERTED (1 << 1) /* autoinstalled */
diff --git a/src/solvversion.h.in b/src/solvversion.h.in
index 75dc63f..9f59d75 100644
--- a/src/solvversion.h.in
+++ b/src/solvversion.h.in
@@ -28,6 +28,7 @@ extern int solv_version_patch;
#cmakedefine LIBSOLV_FEATURE_COMPLEX_DEPS
#cmakedefine LIBSOLV_FEATURE_MULTI_SEMANTICS
+#cmakedefine LIBSOLVEXT_FEATURE_RPMPKG
#cmakedefine LIBSOLVEXT_FEATURE_RPMDB
#cmakedefine LIBSOLVEXT_FEATURE_RPMDB_BYRPMHEADER
#cmakedefine LIBSOLVEXT_FEATURE_PUBKEY
diff --git a/test/testcases/focus/best.t b/test/testcases/focus/best.t
new file mode 100644
index 0000000..a7a46b9
--- /dev/null
+++ b/test/testcases/focus/best.t
@@ -0,0 +1,23 @@
+repo system 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Pkg: A2 1 1 noarch
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Pkg: A 2 1 noarch
+#>=Pkg: B 1 1 noarch
+#>=Req: A = 1
+#>=Pkg: B 2 1 noarch
+#>=Req: A = 2
+#>=Pkg: A2 1 1 noarch
+#>=Pkg: A2 2 1 noarch
+#>=Pkg: B2 1 1 noarch
+#>=Req: A2 = 1
+#>=Pkg: B2 2 1 noarch
+#>=Req: A2 = 2
+#>=Pkg: C 1 1 noarch
+#>=Req: B2
+system i686 rpm system
+solverflags focusbest
+
+job install name B
+job install name C
diff --git a/test/testcases/focus/installed.t b/test/testcases/focus/installed.t
new file mode 100644
index 0000000..4f49d35
--- /dev/null
+++ b/test/testcases/focus/installed.t
@@ -0,0 +1,23 @@
+repo system 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Pkg: A2 1 1 noarch
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Pkg: A 2 1 noarch
+#>=Pkg: B 1 1 noarch
+#>=Req: A = 1
+#>=Pkg: B 2 1 noarch
+#>=Req: A = 2
+#>=Pkg: A2 1 1 noarch
+#>=Pkg: A2 2 1 noarch
+#>=Pkg: B2 1 1 noarch
+#>=Req: A2 = 1
+#>=Pkg: B2 2 1 noarch
+#>=Req: A2 = 2
+#>=Pkg: C 1 1 noarch
+#>=Req: B2
+system i686 rpm system
+solverflags focusinstalled
+
+job install name B
+job install name C
diff --git a/test/testcases/focus/normal.t b/test/testcases/focus/normal.t
new file mode 100644
index 0000000..6e562a3
--- /dev/null
+++ b/test/testcases/focus/normal.t
@@ -0,0 +1,22 @@
+repo system 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Pkg: A2 1 1 noarch
+repo available 0 testtags <inline>
+#>=Pkg: A 1 1 noarch
+#>=Pkg: A 2 1 noarch
+#>=Pkg: B 1 1 noarch
+#>=Req: A = 1
+#>=Pkg: B 2 1 noarch
+#>=Req: A = 2
+#>=Pkg: A2 1 1 noarch
+#>=Pkg: A2 2 1 noarch
+#>=Pkg: B2 1 1 noarch
+#>=Req: A2 = 1
+#>=Pkg: B2 2 1 noarch
+#>=Req: A2 = 2
+#>=Pkg: C 1 1 noarch
+#>=Req: B2
+system i686 rpm system
+
+job install name B
+job install name C
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 16fa097..6b592f7 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -10,15 +10,18 @@ IF (ENABLE_RPMDB)
ADD_EXECUTABLE (rpmdb2solv rpmdb2solv.c)
TARGET_LINK_LIBRARIES (rpmdb2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRARIES})
-ADD_EXECUTABLE (rpms2solv rpms2solv.c)
-TARGET_LINK_LIBRARIES (rpms2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRARIES})
-
ADD_EXECUTABLE (findfileconflicts findfileconflicts.c)
TARGET_LINK_LIBRARIES (findfileconflicts libsolvext libsolv ${SYSTEM_LIBRARIES})
-SET (tools_list ${tools_list} rpmdb2solv rpms2solv)
+SET (tools_list ${tools_list} rpmdb2solv)
ENDIF (ENABLE_RPMDB)
+IF (ENABLE_RPMPKG)
+ADD_EXECUTABLE (rpms2solv rpms2solv.c)
+TARGET_LINK_LIBRARIES (rpms2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRARIES})
+SET (tools_list ${tools_list} rpms2solv)
+ENDIF (ENABLE_RPMPKG)
+
IF (ENABLE_RPMMD)
ADD_EXECUTABLE (repomdxml2solv repomdxml2solv.c)
TARGET_LINK_LIBRARIES (repomdxml2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRARIES})
diff --git a/tools/installcheck.c b/tools/installcheck.c
index e8be171..b0fdb33 100644
--- a/tools/installcheck.c
+++ b/tools/installcheck.c
@@ -49,6 +49,7 @@ usage(char** argv)
exit(1);
}
+#if defined(ENABLE_SUSEREPO) || defined(ENABLE_RPMMD) || defined(ENABLE_DEBIAN) || defined(ENABLE_ARCHREPO)
static int
strlen_comp(const char *str)
{
@@ -63,6 +64,7 @@ strlen_comp(const char *str)
return l - 5;
return l;
}
+#endif
int
main(int argc, char **argv)
@@ -97,7 +99,10 @@ main(int argc, char **argv)
for (i = 2; i < argc; i++)
{
FILE *fp;
- int r, l;
+ int r;
+#if defined(ENABLE_SUSEREPO) || defined(ENABLE_RPMMD) || defined(ENABLE_DEBIAN) || defined(ENABLE_ARCHREPO)
+ int l;
+#endif
if (!strcmp(argv[i], "--withsrc"))
{
@@ -126,7 +131,9 @@ main(int argc, char **argv)
++i;
continue;
}
+#if defined(ENABLE_SUSEREPO) || defined(ENABLE_RPMMD) || defined(ENABLE_DEBIAN) || defined(ENABLE_ARCHREPO)
l = strlen_comp(argv[i]);
+#endif
if (!strcmp(argv[i], "-"))
fp = stdin;
else if ((fp = solv_xfopen(argv[i], 0)) == 0)