ENDIF (DEFINED INCLUDE)
MESSAGE (STATUS "Header files will be installed in ${INCLUDE_INSTALL_DIR}")
SET (BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin")
-SET (MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/man")
-IF (IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/man" AND NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/man")
- SET (MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/man")
-ENDIF (IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/man" AND NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/man")
+SET (MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/man")
+IF (IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/man" AND NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/man")
+ SET (MAN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/man")
+ENDIF (IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/man" AND NOT IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/share/man")
MESSAGE(STATUS "Man pages will be installed in ${MAN_INSTALL_DIR}")
####################################################################
SET(LIBSOLV_MAJOR "0")
SET(LIBSOLV_MINOR "6")
-SET(LIBSOLV_PATCH "20")
+SET(LIBSOLV_PATCH "21")
static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED;
static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED;
static const Id SOLVER_ALLOWUNINSTALL = SOLVER_ALLOWUNINSTALL;
+ static const Id SOLVER_FAVOR = SOLVER_FAVOR;
+ static const Id SOLVER_DISFAVOR = SOLVER_DISFAVOR;
static const Id SOLVER_JOBMASK = SOLVER_JOBMASK;
static const Id SOLVER_WEAK = SOLVER_WEAK;
static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL;
static const int POOL_FLAG_NOINSTALLEDOBSOLETES = POOL_FLAG_NOINSTALLEDOBSOLETES;
static const int POOL_FLAG_HAVEDISTEPOCH = POOL_FLAG_HAVEDISTEPOCH;
static const int POOL_FLAG_NOOBSOLETESMULTIVERSION = POOL_FLAG_NOOBSOLETESMULTIVERSION;
+ static const int DISTTYPE_RPM = DISTTYPE_RPM;
+ static const int DISTTYPE_DEB = DISTTYPE_DEB;
+ static const int DISTTYPE_ARCH = DISTTYPE_ARCH;
+ static const int DISTTYPE_HAIKU = DISTTYPE_HAIKU;
Pool() {
Pool *pool = pool_create();
return pool;
}
+ int setdisttype(int disttype) {
+ return pool_setdisttype($self, disttype);
+ }
void set_debuglevel(int level) {
pool_setdebuglevel($self, level);
}
'\" t
.\" Title: Libsolv-Bindings
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 12/14/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 05/03/2016
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-BINDINGS" "3" "12/14/2015" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-BINDINGS" "3" "05/03/2016" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Allow the solver to deinstall the matching installed packages if they get into the way of resolving a dependency\&. This is like the SOLVER_FLAG_ALLOW_UNINSTALL flag, but limited to a specific set of packages\&.
.RE
.PP
+\fBSOLVER_FAVOR\fR
+.RS 4
+Prefer the specified packages if the solver encounters an alternative\&. If a job contains multiple matching favor/disfavor elements, the last one takes precedence\&.
+.RE
+.PP
+\fBSOLVER_DISFAVOR\fR
+.RS 4
+Avoid the specified packages if the solver encounters an alternative\&. This can also be used to block recommended or supplemented packages from being installed\&.
+.RE
+.PP
\fBSOLVER_JOBMASK\fR
.RS 4
A mask containing all the above action bits\&.
into the way of resolving a dependency. This is like the
SOLVER_FLAG_ALLOW_UNINSTALL flag, but limited to a specific set of packages.
+*SOLVER_FAVOR*::
+Prefer the specified packages if the solver encounters an alternative. If
+a job contains multiple matching favor/disfavor elements, the last one takes
+precedence.
+
+*SOLVER_DISFAVOR*::
+Avoid the specified packages if the solver encounters an alternative. This
+can also be used to block recommended or supplemented packages from being
+installed.
+
*SOLVER_JOBMASK*::
A mask containing all the above action bits.
'\" t
.\" Title: Libsolv-Pool
.\" Author: [see the "Author" section]
-.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 12/14/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 05/06/2016
.\" Manual: LIBSOLV
.\" Source: libsolv
.\" Language: English
.\"
-.TH "LIBSOLV\-POOL" "3" "12/14/2015" "libsolv" "LIBSOLV"
+.TH "LIBSOLV\-POOL" "3" "05/06/2016" "libsolv" "LIBSOLV"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.RE
.\}
.sp
-Set the package type of your system\&. The disttype is used for example to define package comparison semantics\&. Libsolv\(cqs default disttype should match the package manager of your system, so you only need to use this function if you want to use the library to solve packaging problems for different systems\&. The Function returns the old disttype on success, and \-1 if the new disttype is not supported\&.
+Set the package type of your system\&. The disttype is used for example to define package comparison semantics\&. Libsolv\(cqs default disttype should match the package manager of your system, so you only need to use this function if you want to use the library to solve packaging problems for different systems\&. The Function returns the old disttype on success, and \-1 if the new disttype is not supported\&. Note that any pool_setarch and pool_setarchpolicy calls need to come after the pool_setdisttype call, as they make use of the noarch/any/all architecture id\&.
.sp
.if n \{\
.RS 4
use this function if you want to use the library to solve packaging
problems for different systems. The Function returns the old
disttype on success, and -1 if the new disttype is not supported.
+Note that any pool_setarch and pool_setarchpolicy calls need to
+come after the pool_setdisttype call, as they make use of the
+noarch/any/all architecture id.
int pool_set_flag(Pool *pool, int flag, int value);
int
-yesno(const char *str)
+yesno(const char *str, int other)
{
char inbuf[128], *ip;
printf("Abort.\n");
exit(1);
}
- if (*ip == 'y' || *ip == 'n')
- return *ip == 'y' ? 1 : 0;
+ if (*ip == 'y' || *ip == 'n' || *ip == other)
+ return *ip == 'n' ? 0 : *ip;
}
}
int forcebest = 0;
char *rootdir = 0;
char *keyname = 0;
+ int keyname_depstr = 0;
int debuglevel = 0;
+ int answer, acnt = 0;
argc--;
argv++;
argc--;
argv++;
}
- if (argc > 2 && !strcmp(argv[1], "--keyname"))
+ else if (argc > 1 && !strcmp(argv[1], "--depstr"))
+ {
+ keyname_depstr = 1;
+ argc--;
+ argv++;
+ }
+ else if (argc > 2 && !strcmp(argv[1], "--keyname"))
{
keyname = argv[2];
argc -= 2;
if (!keyname)
rflags = selection_make(pool, &job2, argv[i], flags);
else
- rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0);
+ {
+ if (keyname_depstr)
+ flags |= SELECTION_MATCH_DEPSTR;
+ rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0);
+ }
if (repofilter.count)
selection_filter(pool, &job2, &repofilter);
if (archfilter.count)
queue_push2(&job, SOLVER_ERASE|SOLVER_CLEANDEPS|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1));
#endif
-#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA) || defined(MANDRIVA) || defined(MAGEIA))
rerunsolver:
-#endif
solv = solver_create(pool);
solver_set_flag(solv, SOLVER_FLAG_SPLITPROVIDES, 1);
#ifdef FEDORA
printf("install size change: %d K\n", transaction_calc_installsizechange(trans));
printf("\n");
- if (!yesno("OK to continue (y/n)? "))
+ acnt = solver_alternatives_count(solv);
+ if (acnt)
+ {
+ printf("Have %d alternatives\n\n", acnt);
+ answer = yesno("OK to continue (y/n/a)? ", 'a');
+ }
+ else
+ answer = yesno("OK to continue (y/n)? ", 0);
+ if (answer == 'a')
+ {
+ Queue choicesq;
+ Queue answerq;
+ Id id, from, chosen;
+ int j;
+
+ queue_init(&choicesq);
+ queue_init(&answerq);
+ for (i = 1; i <= acnt; i++)
+ {
+ int atype = solver_get_alternative(solv, i, &id, &from, &chosen, &choicesq, 0);
+ printf("\n%s\n", solver_alternative2str(solv, atype, id, from));
+ for (j = 0; j < choicesq.count; j++)
+ {
+ Id p = choicesq.elements[j];
+ if (p < 0)
+ p = -p;
+ queue_push(&answerq, p);
+ printf("%6d: %s\n", answerq.count, pool_solvid2str(pool, p));
+ }
+ }
+ queue_free(&choicesq);
+ printf("\n");
+ for (;;)
+ {
+ char inbuf[128], *ip;
+ int neg = 0;
+ printf("OK to continue (y/n), or number to change alternative: ");
+ fflush(stdout);
+ *inbuf = 0;
+ if (!(ip = fgets(inbuf, sizeof(inbuf), stdin)))
+ {
+ printf("Abort.\n");
+ exit(1);
+ }
+ while (*ip == ' ' || *ip == '\t')
+ ip++;
+ if (*ip == '-' && ip[1] >= '0' && ip[1] <= '9')
+ {
+ neg = 1;
+ ip++;
+ }
+ if (*ip >= '0' && *ip <= '9')
+ {
+ int take = atoi(ip);
+ if (take > 0 && take <= answerq.count)
+ {
+ Id p = answerq.elements[take - 1];
+ queue_free(&answerq);
+ queue_push2(&job, (neg ? SOLVER_DISFAVOR : SOLVER_FAVOR) | SOLVER_SOLVABLE_NAME, pool->solvables[p].name);
+ solver_free(solv);
+ solv = 0;
+ goto rerunsolver;
+ break;
+ }
+ }
+ if (*ip == 'n' || *ip == 'y')
+ {
+ answer = *ip == 'n' ? 0 : *ip;
+ break;
+ }
+ }
+ queue_free(&answerq);
+ }
+ if (!answer)
{
printf("Abort.\n");
transaction_free(trans);
queue_init(&conflicts);
if (checkfileconflicts(pool, &checkq, newpkgs, newpkgsfps, &conflicts))
{
- if (yesno("Re-run solver (y/n/q)? "))
+ if (yesno("Re-run solver (y/n/q)? ", 0))
{
for (i = 0; i < newpkgs; i++)
if (newpkgsfps[i])
IF (ENABLE_SUSEREPO OR ENABLE_RPMMD OR ENABLE_RPMDB)
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_COMPLEX_DEPS)
global:
pool_deb_get_autoinstalled;
pool_findfileconflicts;
+ pool_parserpmrichdep;
repo_add_appdata;
repo_add_appdata_dir;
repo_add_arch_local;
strncpy(md5padded, info->digest, 32);
md5padded[32] = 0;
md5padded[33] = info->color;
- /* printf("%d, hx %x -> %s %d %s\n", cbdata->idx, hx, fn, info->mode, info->digest); */
+ /* printf("%d, hx %x -> %s %d %s %d\n", cbdata->idx, hx, fn, info->mode, info->digest, info->color); */
off = addfilesspace(cbdata, strlen(fn) + (34 + 1));
memcpy(cbdata->filesspace + off, (unsigned char *)md5padded, 34);
strcpy((char *)cbdata->filesspace + off + 34, fn);
void *handle;
Repo *installed = pool->installed;
Id p;
- int obsoleteusescolors = pool_get_flag(pool, POOL_FLAG_OBSOLETEUSESCOLORS);
+ int usefilecolors;
int hdrfetches;
queue_empty(conflicts);
return 0;
now = start = solv_timems(0);
+ /* Hmm, should we have a different flag for this? */
+ usefilecolors = pool_get_flag(pool, POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS);
POOL_DEBUG(SOLV_DEBUG_STATS, "searching for file conflicts\n");
- POOL_DEBUG(SOLV_DEBUG_STATS, "packages: %d, cutoff %d\n", pkgs->count, cutoff);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "packages: %d, cutoff %d, usefilecolors %d\n", pkgs->count, cutoff, usefilecolors);
memset(&cbdata, 0, sizeof(cbdata));
cbdata.aliases = flags & FINDFILECONFLICTS_CHECK_DIRALIASING;
{
Id idx = cbdata.lookat.elements[i + 1];
int iterflags = RPM_ITERATE_FILELIST_WITHMD5 | RPM_ITERATE_FILELIST_NOGHOSTS;
- if (obsoleteusescolors)
+ if (usefilecolors)
iterflags |= RPM_ITERATE_FILELIST_WITHCOL;
p = pkgs->elements[idx];
handle = (*handle_cb)(pool, p, handle_cbdata);
}
if (!strcmp(fsi, fsj))
continue; /* file digests match, no conflict */
- if (obsoleteusescolors && fsi[33] && fsj[33] && (fsi[33] & fsj[33]) == 0)
+ if (usefilecolors && fsi[33] && fsj[33] && (fsi[33] & fsj[33]) == 0)
continue; /* colors do not conflict */
queue_push(conflicts, pool_str2id(pool, fsi + 34, 1));
queue_push(conflicts, pkgs->elements[pidx]);
if (!(p = strchr(p, '\n')))
{
int l3;
- if (l + 1024 >= bufl)
+ while (l + 1024 >= bufl)
{
buf = solv_realloc(buf, bufl + 4096);
bufl += 4096;
- p = buf + l;
- continue;
}
p = buf + l;
ll = fread(p, 1, bufl - l - 1, fp);
while ((l3 = strlen(p)) < ll)
p[l3] = '\n';
l += ll;
+ if (p != buf)
+ p--;
continue;
}
p++;
/* 3: added triggers */
/* 4: fixed triggers */
/* 5: fixed checksum copying */
-#define RPMDB_COOKIE_VERSION 5
+/* 6: add SOLVABLE_PREREQ_IGNOREINST support */
+#define RPMDB_COOKIE_VERSION 6
#define TAG_NAME 1000
#define TAG_VERSION 1001
if ((flags & RPM_ITERATE_FILELIST_WITHCOL) != 0)
{
co = headint32array(rpmhead, TAG_FILECOLORS, &cnt2);
- if (!co || cnt != cnt2)
+ if (co && cnt != cnt2)
{
solv_free(co);
solv_free(md);
info.digest = md5;
}
}
- if (co)
- info.color = co[i];
+ info.color = co ? co[i] : 0;
(*cb)(cbdata, space, &info);
}
solv_free(space);
while (ht[h])
{
unsigned char *d = pd->csdata + ht[h];
- if (d[-1] == keyl && !memcmp(key, d, keyl))
+ if (d[-1] == keyl - 1 && !memcmp(key, d, keyl))
return; /* XXX: first id wins... */
h = HASHCHAIN_NEXT(h, hh, hm);
}
}
/* a new entry. put in csdata */
- pd->csdata = solv_extend(pd->csdata, pd->ncsdata, 1, 1 + keyl + sizeof(Id), 4095);
+ pd->csdata = solv_extend(pd->csdata, pd->ncsdata, 1 + keyl + sizeof(Id), 1, 4095);
d = pd->csdata + pd->ncsdata;
d[0] = keyl - 1;
memcpy(d + 1, key, keyl);
{ SOLVER_DROP_ORPHANED, "droporphaned" },
{ SOLVER_USERINSTALLED, "userinstalled" },
{ SOLVER_ALLOWUNINSTALL, "allowuninstall" },
+ { SOLVER_FAVOR, "favor" },
+ { SOLVER_DISFAVOR, "disfavor" },
{ 0, 0 }
};
{ TESTCASE_RESULT_ALTERNATIVES, "alternatives" },
{ TESTCASE_RESULT_RULES, "rules" },
{ TESTCASE_RESULT_GENID, "genid" },
+ { TESTCASE_RESULT_REASON, "reason" },
{ 0, 0 }
};
{ SOLVER_FLAG_FOCUS_INSTALLED, "focusinstalled", 0 },
{ SOLVER_FLAG_YUM_OBSOLETES, "yumobsoletes", 0 },
{ SOLVER_FLAG_NEED_UPDATEPROVIDE, "needupdateprovide", 0 },
+ { SOLVER_FLAG_URPM_REORDER, "urpmreorder", 0 },
{ 0, 0, 0 }
};
pool_debug(solv->pool, SOLV_ERROR, "setsolverflags: unknown flag '%.*s'\n", (int)(p - s), s);
return 0;
}
- solver_set_flag(solv, solverflags2str[i].flag, v);
+ if (solver_set_flag(solv, solverflags2str[i].flag, v) == -1)
+ {
+ pool_debug(solv->pool, SOLV_ERROR, "setsolverflags: unsupported flag '%s'\n", solverflags2str[i].str);
+ return 0;
+ }
}
return 1;
}
{ 0, 0 }
};
+static struct reason2str {
+ Id reason;
+ const char *str;
+} reason2str[] = {
+ { SOLVER_REASON_UNRELATED, "unrelated" },
+ { SOLVER_REASON_UNIT_RULE, "unit" },
+ { SOLVER_REASON_KEEP_INSTALLED, "keep" },
+ { SOLVER_REASON_RESOLVE_JOB, "job" },
+ { SOLVER_REASON_UPDATE_INSTALLED, "update" },
+ { SOLVER_REASON_CLEANDEPS_ERASE, "cleandeps" },
+ { SOLVER_REASON_RESOLVE, "resolve" },
+ { SOLVER_REASON_WEAKDEP, "weakdep" },
+ { SOLVER_REASON_RESOLVE_ORPHAN, "orphan" },
+
+ { SOLVER_REASON_RECOMMENDED, "recommended" },
+ { SOLVER_REASON_SUPPLEMENTED, "supplemented" },
+ { 0, 0 }
+};
+
+static const char *
+testcase_reason2str(Id reason)
+{
+ int i;
+ for (i = 0; reason2str[i].str; i++)
+ if (reason == reason2str[i].reason)
+ return reason2str[i].str;
+ return "?";
+}
+
static int
dump_genid(Pool *pool, Strqueue *sq, Id id, int cnt)
{
dump_genid(pool, &sq, id, 1);
}
}
+ if ((resultflags & TESTCASE_RESULT_REASON) != 0)
+ {
+ Queue whyq;
+ queue_init(&whyq);
+ FOR_POOL_SOLVABLES(p)
+ {
+ Id info, p2, id;
+ int reason = solver_describe_decision(solv, p, &info);
+ if (reason == SOLVER_REASON_UNRELATED)
+ continue;
+ if (reason == SOLVER_REASON_WEAKDEP)
+ {
+ solver_describe_weakdep_decision(solv, p, &whyq);
+ if (whyq.count)
+ {
+ for (i = 0; i < whyq.count; i += 3)
+ {
+ reason = whyq.elements[i];
+ p2 = whyq.elements[i + 1];
+ id = whyq.elements[i + 2];
+ s = pool_tmpjoin(pool, "reason ", testcase_solvid2str(pool, p), 0);
+ s = pool_tmpappend(pool, s, " ", testcase_reason2str(reason));
+ s = pool_tmpappend(pool, s, " ", testcase_dep2str(pool, id));
+ if (p2)
+ s = pool_tmpappend(pool, s, " ", testcase_solvid2str(pool, p2));
+ strqueue_push(&sq, s);
+ }
+ continue;
+ }
+ }
+ s = pool_tmpjoin(pool, "reason ", testcase_solvid2str(pool, p), 0);
+ s = pool_tmpappend(pool, s, " ", testcase_reason2str(reason));
+ if (info)
+ s = pool_tmpappend(pool, s, " ", testcase_ruleid(solv, info));
+ strqueue_push(&sq, s);
+ }
+ queue_free(&whyq);
+ }
strqueue_sort(&sq);
result = strqueue_join(&sq);
strqueue_free(&sq);
#define TESTCASE_RESULT_ALTERNATIVES (1 << 5)
#define TESTCASE_RESULT_RULES (1 << 6)
#define TESTCASE_RESULT_GENID (1 << 7)
+#define TESTCASE_RESULT_REASON (1 << 8)
extern Id testcase_str2dep(Pool *pool, const char *s);
extern const char *testcase_dep2str(Pool *pool, Id id);
-------------------------------------------------------------------
+Wed May 18 15:09:56 CEST 2016 - mls@suse.de
+
+- add pool->setdisttype to the bindings
+- fix error in repo_deb that could lead to missing packages
+- add reason testing to testcase code
+- add pool_whatcontainsdep, selection_make_matchdepid, and
+ SELECTION_MATCH_DEPSTR
+- add SOLVER_FAVOR and SOLVER_DISFAVOR job types
+- allow unknown archs in pool_setarch
+- add the SOLVER_FLAG_URPM_REORDER solver flag
+- fix segfault in cshash dedup code
+- fix supplements handling when implicitobsoleteusescolors is set
+- bump version to 0.6.21
+
+-------------------------------------------------------------------
Fri Apr 8 15:36:21 CEST 2016 - mls@suse.de
- Better support of complex deps in pool_match_dep and
pool_trivial_installable_multiversionmap;
pool_vendor2mask;
pool_whatmatchesdep;
+ pool_whatcontainsdep;
queue_alloc_one;
queue_alloc_one_head;
queue_delete;
selection_add;
selection_filter;
selection_make;
+ selection_make_matchdepid;
selection_make_matchdeps;
selection_solvables;
solv_bin2hex;
}
}
+static int
+sort_by_favorq_cmp(const void *ap, const void *bp, void *dp)
+{
+ const Id *a = ap, *b = bp, *d = dp;
+ return d[b[0]] - d[a[0]];
+}
+
+static void
+sort_by_favorq(Queue *favorq, Id *el, int cnt)
+{
+ int i;
+ /* map to offsets into favorq */
+ for (i = 0; i < cnt; i++)
+ {
+ Id p = el[i];
+ /* lookup p in sorted favorq */
+ int med = 0, low = 0;
+ int high = favorq->count / 2;
+ while (low != high)
+ {
+ med = (low + high) / 2;
+ Id pp = favorq->elements[2 * med];
+ if (pp < p)
+ low = med;
+ else if (pp > p)
+ high = med;
+ else
+ break;
+ }
+ while(med && favorq->elements[2 * med - 2] == p)
+ med--;
+ if (favorq->elements[2 * med] == p)
+ el[i] = 2 * med + 1;
+ else
+ el[i] = 0; /* hmm */
+ }
+ /* sort by position */
+ solv_sort(el, cnt, sizeof(Id), sort_by_favorq_cmp, favorq->elements);
+ /* map back */
+ for (i = 0; i < cnt; i++)
+ if (el[i])
+ el[i] = favorq->elements[el[i] - 1];
+}
+
+/* bring favored packages to front and disfavored packages to back */
+void
+policy_prefer_favored(Solver *solv, Queue *plist)
+{
+ int i, fav, disfav, count;
+ if (!solv->favormap.size)
+ return;
+ for (i = fav = disfav = 0, count = plist->count; i < count; i++)
+ {
+ Id p = plist->elements[i];
+ if (!MAPTST(&solv->favormap, p))
+ continue;
+ if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p))
+ {
+ /* disfavored package. bring to back */
+ if (i < plist->count - 1)
+ {
+ memmove(plist->elements + i, plist->elements + i + 1, (plist->count - 1 - i) * sizeof(Id));
+ plist->elements[plist->count - 1] = p;
+ }
+ i--;
+ count--;
+ disfav++;
+ }
+ else
+ {
+ /* favored package. bring to front */
+ if (i > fav)
+ memmove(plist->elements + fav + 1, plist->elements + fav, (i - fav) * sizeof(Id));
+ plist->elements[fav++] = p;
+ }
+ }
+ /* if we have multiple favored/disfavored packages, sort by favorq index */
+ if (fav > 1)
+ sort_by_favorq(solv->favorq, plist->elements, fav);
+ if (disfav > 1)
+ sort_by_favorq(solv->favorq, plist->elements + plist->count - disfav, disfav);
+}
+
/*
* prune to recommended/suggested packages.
* does not prune installed packages (they are also somewhat recommended).
}
}
+
+/* special lang package handling for urpm */
+/* see https://bugs.mageia.org/show_bug.cgi?id=18315 */
+
+static int
+urpm_reorder_cmp(const void *ap, const void *bp, void *dp)
+{
+ return ((Id *)bp)[1] - ((Id *)ap)[1];
+}
+
+static void
+urpm_reorder(Solver *solv, Queue *plist)
+{
+ Pool *pool = solv->pool;
+ int i, count = plist->count;
+ /* add locale score to packages */
+ queue_insertn(plist, count, count, 0);
+ for (i = count - 1; i >= 0; i--)
+ {
+ Solvable *s = pool->solvables + plist->elements[i];
+ int score = 1;
+ const char *sn = pool_id2str(pool, s->name);
+
+ if (!strncmp(sn, "kernel-", 7))
+ {
+ const char *devel = strstr(sn, "-devel-");
+ if (devel && strlen(sn) < 256)
+ {
+ char kn[256];
+ Id p, pp, knid;
+ memcpy(kn, sn, devel - sn);
+ strcpy(kn + (devel - sn), devel + 6);
+ knid = pool_str2id(pool, kn, 0);
+ if (knid)
+ {
+ FOR_PROVIDES(p, pp, knid)
+ if (solv->decisionmap[p] > 0 || (pool->installed && pool->solvables[p].repo == pool->installed))
+ score = 3;
+ }
+ }
+ }
+ else if ((sn = strstr(sn, "-kernel-")) != 0)
+ {
+ sn += 8;
+ if (strlen(sn) < 256 - 8 && *sn >= '0' && *sn <= '9' && sn[1] == '.')
+ {
+ const char *flavor = strchr(sn, '-');
+ if (flavor)
+ {
+ const char *release = strchr(flavor + 1, '-');
+ if (release)
+ {
+ char kn[256];
+ Id p, pp, knid;
+ memcpy(kn, "kernel", 8);
+ memcpy(kn + 6, flavor, release - flavor + 1);
+ memcpy(kn + 6 + (release - flavor) + 1, sn, flavor - sn);
+ strcpy(kn + 6 + (release + 1 - sn), release);
+ knid = pool_str2id(pool, kn, 0);
+ if (knid)
+ {
+ FOR_PROVIDES(p, pp, knid)
+ if (solv->decisionmap[p] > 0 || (pool->installed && pool->solvables[p].repo == pool->installed))
+ score = 3;
+ }
+ }
+ }
+ }
+ }
+ if (score == 1 && s->requires)
+ {
+ Id id, *idp, p, pp;
+ const char *deps;
+ for (idp = s->repo->idarraydata + s->requires; (id = *idp) != 0; idp++)
+ {
+ while (ISRELDEP(id))
+ {
+ Reldep *rd = GETRELDEP(pool, id);
+ id = rd->name;
+ }
+ deps = strstr(pool_id2str(pool, id), "locales-");
+ if (!deps)
+ continue;
+ if (!strncmp(deps + 8, "en", 2))
+ score = 2;
+ else
+ {
+ score = 0;
+ FOR_PROVIDES(p, pp, id)
+ if (solv->decisionmap[p] > 0 || (pool->installed && pool->solvables[p].repo == pool->installed))
+ score = 3;
+ break;
+ }
+ }
+ }
+ plist->elements[i * 2] = plist->elements[i];
+ plist->elements[i * 2 + 1] = score;
+ }
+ solv_sort(plist->elements, count, sizeof(Id) * 2, urpm_reorder_cmp, pool);
+ for (i = 0; i < count; i++)
+ plist->elements[i] = plist->elements[2 * i];
+ queue_truncate(plist, count);
+}
+
+
/*
* POLICY_MODE_CHOOSE: default, do all pruning steps
* POLICY_MODE_RECOMMEND: leave out prune_to_recommended
policy_filter_unwanted(Solver *solv, Queue *plist, int mode)
{
Pool *pool = solv->pool;
+ if (mode == POLICY_MODE_SUPPLEMENT)
+ {
+ /* reorder only */
+ dislike_old_versions(pool, plist);
+ sort_by_common_dep(pool, plist);
+ if (solv->urpmreorder)
+ urpm_reorder(solv, plist);
+ prefer_suggested(solv, plist);
+ policy_prefer_favored(solv, plist);
+ return;
+ }
if (plist->count > 1)
{
if (mode != POLICY_MODE_SUGGEST)
#endif
dislike_old_versions(pool, plist);
sort_by_common_dep(pool, plist);
+ if (solv->urpmreorder)
+ urpm_reorder(solv, plist);
prefer_suggested(solv, plist);
+ policy_prefer_favored(solv, plist);
}
}
}
#define POLICY_MODE_RECOMMEND 1
#define POLICY_MODE_SUGGEST 2
#define POLICY_MODE_CHOOSE_NOREORDER 3 /* internal, do not use */
+#define POLICY_MODE_SUPPLEMENT 4 /* internal, do not use */
#define POLICY_ILLEGAL_DOWNGRADE 1
/* internal, do not use */
extern void prune_to_best_version(Pool *pool, Queue *plist);
+extern void policy_prefer_favored(Solver *solv, Queue *plist);
#ifdef __cplusplus
pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
{
Id p;
+ Queue qq;
+ int i;
queue_empty(q);
+ queue_init(&qq);
FOR_POOL_SOLVABLES(p)
{
Solvable *s = pool->solvables + p;
continue;
if (s->repo != pool->installed && !pool_installable(pool, s))
continue;
- if (solvable_matchesdep(s, keyname, dep, marker))
- queue_push(q, p);
+ if (qq.count)
+ queue_empty(&qq);
+ solvable_lookup_deparray(s, keyname, &qq, marker);
+ for (i = 0; i < qq.count; i++)
+ if (pool_match_dep(pool, qq.elements[i], dep))
+ {
+ queue_push(q, p);
+ break;
+ }
+ }
+ queue_free(&qq);
+}
+
+/* check if keyname contains dep, return list of matching packages */
+void
+pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
+{
+ Id p;
+ Queue qq;
+ int i;
+
+ queue_empty(q);
+ if (!dep)
+ return;
+ queue_init(&qq);
+ FOR_POOL_SOLVABLES(p)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo->disabled)
+ continue;
+ if (s->repo != pool->installed && !pool_installable(pool, s))
+ continue;
+ if (qq.count)
+ queue_empty(&qq);
+ solvable_lookup_deparray(s, keyname, &qq, marker);
+ for (i = 0; i < qq.count; i++)
+ if (qq.elements[i] == dep)
+ {
+ queue_push(q, p);
+ break;
+ }
}
+ queue_free(&qq);
}
/*************************************************************************/
}
void pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker);
+void pool_whatcontainsdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker);
/* search the pool. the following filters are available:
* p - search just this solvable
"i686", "i686:i586:i486:i386",
"i586", "i586:i486:i386",
"i486", "i486:i386",
- "i386", "i386",
"s390x", "s390x:s390",
- "s390", "s390",
- "ppc64le", "ppc64le",
"ppc64", "ppc64:ppc",
- "ppc", "ppc",
"ppc64p7", "ppc64p7:ppc64:ppc",
"ia64", "ia64:i686:i586:i486:i386",
- "aarch64", "aarch64",
- "armv6hl", "armv6hl",
"armv7hnl", "armv7hnl:armv7hl:armv6hl",
"armv7hl", "armv7hl:armv6hl",
"armv7l", "armv7l:armv6l:armv5tejl:armv5tel:armv5l:armv4tl:armv4l:armv3l",
"armv5l", "armv5l:armv4tl:armv4l:armv3l",
"armv4tl", "armv4tl:armv4l:armv3l",
"armv4l", "armv4l:armv3l",
- "armv3l", "armv3l",
- "sh3", "sh3",
- "sh4", "sh4",
"sh4a", "sh4a:sh4",
"sparc64v", "sparc64v:sparc64:sparcv9v:sparcv9:sparcv8:sparc",
"sparc64", "sparc64:sparcv9:sparcv8:sparc",
"sparcv9v", "sparcv9v:sparcv9:sparcv8:sparc",
"sparcv9", "sparcv9:sparcv8:sparc",
"sparcv8", "sparcv8:sparc",
- "sparc", "sparc",
- "mips", "mips",
- "mipsel", "mipsel",
- "mips64", "mips64",
- "mips64el", "mips64el",
- "m68k", "m68k",
#if defined(FEDORA) || defined(MAGEIA)
"ia32e", "ia32e:x86_64:athlon:i686:i586:i486:i386",
"athlon", "athlon:i686:i586:i486:i386",
if (arch)
{
int i;
-
/* convert arch to known policy */
for (i = 0; archpolicies[i]; i += 2)
if (!strcmp(archpolicies[i], arch))
- break;
- if (archpolicies[i])
- arch = archpolicies[i + 1];
- else
- arch = "";
+ {
+ arch = archpolicies[i + 1];
+ break;
+ }
}
pool_setarchpolicy(pool, arch);
}
return ret;
}
+static inline int
+matchdep_str(const char *pattern, const char *string, int flags)
+{
+ if (flags & SELECTION_GLOB)
+ {
+ int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
+ return fnmatch(pattern, string, globflags) == 0 ? 1 : 0;
+ }
+ if (flags & SELECTION_NOCASE)
+ return strcasecmp(pattern, string) == 0 ? 1 : 0;
+ return strcmp(pattern, string) == 0 ? 1 : 0;
+}
+
static int
matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
{
}
return 1;
}
- if (flags & SELECTION_GLOB)
- {
- int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
- return fnmatch(rname, pool_id2str(pool, id), globflags) == 0 ? 1 : 0;
- }
- if (flags & SELECTION_NOCASE)
- return strcasecmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
- return strcmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
+ return matchdep_str(rname, pool_id2str(pool, id), flags);
}
/*
int
selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker)
{
- char *rname, *r;
+ char *rname, *r = 0;
int rflags = 0;
Id p;
Queue q;
queue_empty(selection);
rname = solv_strdup(name);
- if ((r = strpbrk(rname, "<=>")) != 0)
+ if (!(flags & SELECTION_MATCH_DEPSTR))
{
- if ((r = splitrel(rname, r, &rflags)) == 0)
+ if ((r = strpbrk(rname, "<=>")) != 0)
{
- solv_free(rname);
- return 0;
+ if ((r = splitrel(rname, r, &rflags)) == 0)
+ {
+ solv_free(rname);
+ return 0;
+ }
}
}
- if ((flags & SELECTION_GLOB) != 0 && !strpbrk(name, "[*?") != 0)
+ if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0)
flags &= ~SELECTION_GLOB;
queue_init(&q);
for (i = 0; i < q.count; i++)
{
Id id = q.elements[i];
+ if ((flags & SELECTION_MATCH_DEPSTR) != 0)
+ {
+ if (matchdep_str(rname, pool_dep2str(pool, id), flags))
+ break;
+ continue;
+ }
if (matchdep(pool, id, rname, rflags, r, flags))
break;
}
return SELECTION_PROVIDES;
}
+int
+selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker)
+{
+ Id p;
+ Queue q;
+
+ queue_empty(selection);
+ if (!dep)
+ return 0;
+ queue_init(&q);
+ FOR_POOL_SOLVABLES(p)
+ {
+ Solvable *s = pool->solvables + p;
+ int i;
+
+ if (s->repo != pool->installed && !pool_installable(pool, s))
+ {
+ if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
+ continue;
+ if (pool_disabled_solvable(pool, s))
+ continue;
+ }
+ if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
+ continue;
+ if ((s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) && !(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
+ continue;
+ queue_empty(&q);
+ repo_lookup_deparray(s->repo, p, keyname, &q, marker);
+ for (i = 0; i < q.count; i++)
+ {
+ if ((flags & SELECTION_MATCH_DEPSTR) != 0) /* mis-use */
+ {
+ if (q.elements[i] == dep)
+ break;
+ continue;
+ }
+ if (pool_match_dep(pool, q.elements[i], dep))
+ break;
+ }
+ if (i < q.count)
+ queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, p);
+ }
+ queue_free(&q);
+ if (!selection->count)
+ return 0;
+ if ((flags & SELECTION_FLAT) != 0)
+ selection_flatten(pool, selection);
+ return SELECTION_PROVIDES;
+}
+
static inline int
pool_is_kind(Pool *pool, Id name, Id kind)
{
#define SELECTION_SOURCE_ONLY (1 << 12)
#define SELECTION_WITH_SOURCE (1 << 13)
#define SELECTION_SKIP_KIND (1 << 14)
+#define SELECTION_MATCH_DEPSTR (1 << 15)
extern int selection_make(Pool *pool, Queue *selection, const char *name, int flags);
extern int selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker);
+extern int selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker);
extern void selection_filter(Pool *pool, Queue *sel1, Queue *sel2);
extern void selection_add(Pool *pool, Queue *sel1, Queue *sel2);
solv->recommends_index = -1;
queue_truncate(&solv->decisionq, decisionqcount);
}
+ /* but obey favored maps */
+ policy_prefer_favored(solv, dq);
}
/*-------------------------------------------------------------------
queuep_free(&solv->recommendscplxq);
queuep_free(&solv->suggestscplxq);
queuep_free(&solv->brokenorphanrules);
+ queuep_free(&solv->favorq);
map_free(&solv->recommendsmap);
map_free(&solv->suggestsmap);
map_free(&solv->droporphanedmap);
map_free(&solv->cleandepsmap);
map_free(&solv->allowuninstallmap);
+ map_free(&solv->favormap);
+ map_free(&solv->isdisfavormap);
solv_free(solv->decisionmap);
solv_free(solv->rules);
return solv->do_yum_obsoletes;
case SOLVER_FLAG_NEED_UPDATEPROVIDE:
return solv->needupdateprovide;
+ case SOLVER_FLAG_URPM_REORDER:
+ return solv->urpmreorder;
default:
break;
}
case SOLVER_FLAG_NEED_UPDATEPROVIDE:
solv->needupdateprovide = value;
break;
+ case SOLVER_FLAG_URPM_REORDER:
+ solv->urpmreorder = value;
+ break;
default:
break;
}
#endif
+static void
+prune_disfavored(Solver *solv, Queue *plist)
+{
+ int i, j;
+ if (!solv->isdisfavormap.size)
+ return;
+ for (i = j = 0; i < plist->count; i++)
+ {
+ Id p = plist->elements[i];
+ if (!MAPTST(&solv->isdisfavormap, p))
+ plist->elements[j++] = p;
+ }
+ if (i != j)
+ queue_truncate(plist, j);
+}
+
/*-------------------------------------------------------------------
*
* solver_run_sat
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)
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 < dq.count; i++)
MAPSET(&dqmap, dq.elements[i]);
- /* install all supplemented packages */
+ /* 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] || !MAPTST(&dqmap, p))
+ if (solv->decisionmap[p])
continue;
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
olevel = level;
}
#endif
+/* sort by package id, last entry wins */
+static int
+setup_favormaps_cmp(const void *ap, const void *bp, void *dp)
+{
+ const Id *a = ap, *b = bp;
+ if ((*a - *b) != 0)
+ return *a - *b;
+ return (b[1] < 0 ? -b[1] : b[1]) - (a[1] < 0 ? -a[1] : a[1]);
+}
+
+static void
+setup_favormaps(Solver *solv)
+{
+ Queue *q = solv->favorq;
+ Pool *pool = solv->pool;
+ int i;
+ Id oldp = 0;
+ if (q->count > 2)
+ solv_sort(q->elements, q->count / 2, 2 * sizeof(Id), setup_favormaps_cmp, solv);
+ map_grow(&solv->favormap, pool->nsolvables);
+ for (i = 0; i < q->count; i += 2)
+ {
+ Id p = q->elements[i];
+ if (p == oldp)
+ continue;
+ oldp = p;
+ MAPSET(&solv->favormap, p);
+ if (q->elements[i + 1] < 0)
+ {
+ if (!solv->isdisfavormap.size)
+ map_grow(&solv->isdisfavormap, pool->nsolvables);
+ MAPSET(&solv->isdisfavormap, p);
+ }
+ }
+}
+
/*
*
* solve job queue
map_zerosize(&solv->allowuninstallmap);
map_zerosize(&solv->cleandepsmap);
map_zerosize(&solv->weakrulemap);
+ map_zerosize(&solv->favormap);
+ map_zerosize(&solv->isdisfavormap);
queue_empty(&solv->weakruleq);
solv->watches = solv_free(solv->watches);
queue_empty(&solv->ruletojob);
case SOLVER_ALLOWUNINSTALL:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: allowuninstall %s\n", solver_select2str(pool, select, what));
break;
+ case SOLVER_FAVOR:
+ case SOLVER_DISFAVOR:
+ POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s %s\n", (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? "favor" : "disfavor", solver_select2str(pool, select, what));
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ int j;
+ if (!solv->favorq)
+ {
+ solv->favorq = solv_calloc(1, sizeof(Queue));
+ queue_init(solv->favorq);
+ }
+ j = solv->favorq->count + 1;
+ queue_push2(solv->favorq, p, (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? j : -j);
+ }
+ break;
default:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
break;
assert(solv->ruletojob.count == solv->nrules - solv->jobrules);
solv->jobrules_end = solv->nrules;
+ /* transform favorq into two maps */
+ if (solv->favorq)
+ setup_favormaps(solv);
+
/* now create infarch and dup rules */
if (!solv->noinfarchcheck)
{
case SOLVER_ALLOWUNINSTALL:
strstart = "allow deinstallation of ";
break;
+ case SOLVER_FAVOR:
+ strstart = "favor ";
+ break;
+ case SOLVER_DISFAVOR:
+ strstart = "disfavor ";
+ break;
default:
strstart = "unknown job ";
break;
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 do_yum_obsoletes; /* true: add special yumobs rules */
+ int urpmreorder; /* true: do special urpm package reordering */
Map dupmap; /* dup these packages*/
int dupmap_all; /* dup all packages */
Map allowuninstallmap; /* ok to uninstall those */
int allowuninstall_all;
+ Queue *favorq;
+ Map favormap; /* favored / disfavored packages */
+ Map isdisfavormap;
#endif /* LIBSOLV_INTERNAL */
};
#define SOLVER_DROP_ORPHANED 0x0900
#define SOLVER_USERINSTALLED 0x0a00
#define SOLVER_ALLOWUNINSTALL 0x0b00
+#define SOLVER_FAVOR 0x0c00
+#define SOLVER_DISFAVOR 0x0d00
#define SOLVER_JOBMASK 0xff00
#define SOLVER_FLAG_FOCUS_INSTALLED 20
#define SOLVER_FLAG_YUM_OBSOLETES 21
#define SOLVER_FLAG_NEED_UPDATEPROVIDE 22
+#define SOLVER_FLAG_URPM_REORDER 23
#define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead of ids */
#define GET_USERINSTALLED_INVERTED (1 << 1) /* autoinstalled */
--- /dev/null
+repo system 0 empty
+repo test 0 testtags <inline>
+#>=Ver: 2.0
+#>=Pkg: A 1 1 noarch
+#>=Rec: X
+#>=Pkg: B 1 1 noarch
+#>=Prv: X
+#>=Pkg: C 1 1 noarch
+#>=Prv: X
+system unset * system
+
+# first favor B
+job install name A
+job favor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+# then favor C
+nextjob
+job install name A
+job favor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+# check disfavor
+nextjob
+job install name A
+job disfavor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+nextjob
+job install name A
+job disfavor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+# check disfavor both, this is different from
+# the requires case
+
+nextjob
+job install name A
+job disfavor name B
+job disfavor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
--- /dev/null
+repo system 0 empty
+repo test 0 testtags <inline>
+#>=Ver: 2.0
+#>=Pkg: A 1 1 noarch
+#>=Req: X
+#>=Pkg: B 1 1 noarch
+#>=Prv: X
+#>=Pkg: C 1 1 noarch
+#>=Prv: X
+system unset * system
+
+# first favor B
+job install name A
+job favor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+# then favor C
+nextjob
+job install name A
+job favor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+
+# if both are favored, the last one wins
+nextjob
+job install name A
+job favor name C
+job favor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+nextjob
+job install name A
+job favor name B
+job favor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+# now test disfavor
+
+# first disfavor B
+nextjob
+job install name A
+job disfavor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+# then disfavor C
+nextjob
+job install name A
+job disfavor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+# then both
+nextjob
+job install name A
+job disfavor name B
+job disfavor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+nextjob
+job install name A
+job disfavor name C
+job disfavor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+# then test combination
+nextjob
+job install name A
+job favor name B
+job disfavor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+nextjob
+job install name A
+job disfavor name B
+job favor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+nextjob
+job install name A
+job favor name C
+job disfavor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+nextjob
+job install name A
+job disfavor name C
+job favor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
--- /dev/null
+repo system 0 empty
+repo test 0 testtags <inline>
+#>=Ver: 2.0
+#>=Pkg: A 1 1 noarch
+#>=Pkg: B 1 1 noarch
+#>=Sup: A
+#>=Pkg: C 1 1 noarch
+#>=Sup: A
+#>=Pkg: A2 1 1 noarch
+#>=Pkg: B2 1 1 noarch
+#>=Sup: A2
+#>=Pkg: C2 1 1 noarch
+#>=Sup: A2
+#>=Con: B2
+system unset * system
+
+# first favor B
+job install name A
+job favor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+# then favor C
+nextjob
+job install name A
+job favor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+# same with A2 where B2 and C2 conflict
+
+nextjob
+job install name A2
+job favor name B2
+result transaction,problems <inline>
+#>install A2-1-1.noarch@test
+#>install B2-1-1.noarch@test
+
+nextjob
+job install name A2
+job favor name C2
+result transaction,problems <inline>
+#>install A2-1-1.noarch@test
+#>install C2-1-1.noarch@test
+
+
+# check disfavor
+nextjob
+job install name A
+job disfavor name B
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install C-1-1.noarch@test
+
+nextjob
+job install name A
+job disfavor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
+#>install B-1-1.noarch@test
+
+nextjob
+job install name A
+job disfavor name B
+job disfavor name C
+result transaction,problems <inline>
+#>install A-1-1.noarch@test
--- /dev/null
+repo system 0 empty
+repo test 0 testtags <inline>
+#>=Ver: 2.0
+#>=Pkg: A 1 1 noarch
+#>=Pkg: B 1 1 x86_64
+#>=Sup: A
+#>=Pkg: B 1 1 i686
+#>=Sup: A
+#>=Pkg: A2 1 1 noarch
+#>=Pkg: B2 1 1 x86_64
+#>=Sup: A2
+#>=Req: XX
+#>=Pkg: B2 1 1 i686
+#>=Sup: A2
+system x86_64 * system
+poolflags implicitobsoleteusescolors
+job install name A
+
+nextjob
+job install name A2
FILE *fp;
char buf[4096], *p;
const char *basefile = 0;
+ int is_repo = 0;
- while ((c = getopt(argc, argv, "0b:m:")) >= 0)
+ while ((c = getopt(argc, argv, "0b:m:r")) >= 0)
{
switch(c)
{
case 'm':
manifest = optarg;
break;
+ case 'r':
+ is_repo = 1;
+ break;
case '0':
manifest0 = 1;
break;
repo = repo_create(pool, "deb2solv");
repo_add_repodata(repo, 0);
res = 0;
+ if (!ndebs && !manifest && is_repo)
+ {
+ if (repo_add_debpackages(repo, stdin, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE))
+ {
+ fprintf(stderr, "deb2solv: %s\n", pool_errstr(pool));
+ res = 1;
+ }
+ }
for (i = 0; i < ndebs; i++)
{
+ if (is_repo)
+ {
+ if ((fp = fopen(debs[i], "r")) == 0)
+ {
+ perror(debs[i]);
+ res = 1;
+ continue;
+ }
+ if (repo_add_debpackages(repo, fp, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE))
+ {
+ fprintf(stderr, "deb2solv: %s\n", pool_errstr(pool));
+ res = 1;
+ }
+ fclose(fp);
+ continue;
+ }
if (repo_add_deb(repo, debs[i], REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE) == 0)
{
fprintf(stderr, "deb2solv: %s\n", pool_errstr(pool));