summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2013-09-04 18:54:57 +0200
committerMichael Schroeder <mls@suse.de>2013-09-04 18:54:57 +0200
commit813ed1da5594e3fcde37f9f23120f70791e7a596 (patch)
tree5f2cbf1d0190a3a1f71c88489b0ef85ed968bde7
parent9baad7fefcf3152882fe5d31bb386e64839d5929 (diff)
downloadlibsolv-813ed1da5594e3fcde37f9f23120f70791e7a596.tar.gz
libsolv-813ed1da5594e3fcde37f9f23120f70791e7a596.tar.bz2
libsolv-813ed1da5594e3fcde37f9f23120f70791e7a596.zip
add pool_whatmatchesdep and selection_make_deps to query for packages intersecting a dependency
-rw-r--r--examples/solv.c21
-rw-r--r--src/libsolv.ver2
-rw-r--r--src/pool.c19
-rw-r--r--src/pool.h2
-rw-r--r--src/selection.c158
-rw-r--r--src/selection.h2
-rw-r--r--src/solvable.c17
-rw-r--r--src/solvable.h1
8 files changed, 194 insertions, 28 deletions
diff --git a/examples/solv.c b/examples/solv.c
index 7d6de97..d4a6b6c 100644
--- a/examples/solv.c
+++ b/examples/solv.c
@@ -2598,6 +2598,7 @@ main(int argc, char **argv)
int cleandeps = 0;
int forcebest = 0;
char *rootdir = 0;
+ char *keyname = 0;
argc--;
argv++;
@@ -2669,7 +2670,6 @@ main(int argc, char **argv)
argc -= 2;
argv += 2;
}
-
else if (argc > 1 && !strcmp(argv[1], "--clean"))
{
cleandeps = 1;
@@ -2682,6 +2682,12 @@ main(int argc, char **argv)
argc--;
argv++;
}
+ if (argc > 2 && !strcmp(argv[1], "--keyname"))
+ {
+ keyname = argv[2];
+ argc -= 2;
+ argv += 2;
+ }
else
break;
}
@@ -2851,6 +2857,8 @@ main(int argc, char **argv)
#endif
pool_createwhatprovides(pool);
+ if (keyname)
+ keyname = solv_dupjoin("solvable:", keyname, 0);
queue_init(&job);
for (i = 1; i < argc; i++)
{
@@ -2869,13 +2877,19 @@ main(int argc, char **argv)
flags |= SELECTION_WITH_SOURCE;
if (argv[i][0] == '/')
flags |= SELECTION_FILELIST | (mode == MODE_ERASE ? SELECTION_INSTALLED_ONLY : 0);
- rflags = selection_make(pool, &job2, argv[i], flags);
+ if (!keyname)
+ rflags = selection_make(pool, &job2, argv[i], flags);
+ else
+ rflags = selection_make_deps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1));
if (repofilter.count)
selection_filter(pool, &job2, &repofilter);
if (!job2.count)
{
flags |= SELECTION_NOCASE;
- rflags = selection_make(pool, &job2, argv[i], flags);
+ if (!keyname)
+ rflags = selection_make(pool, &job2, argv[i], flags);
+ else
+ rflags = selection_make_deps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1));
if (repofilter.count)
selection_filter(pool, &job2, &repofilter);
if (job2.count)
@@ -2894,6 +2908,7 @@ main(int argc, char **argv)
queue_push(&job, job2.elements[j]);
queue_free(&job2);
}
+ keyname = solv_free(keyname);
if (!job.count && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE || mainmode == MODE_VERIFY || repofilter.count))
{
diff --git a/src/libsolv.ver b/src/libsolv.ver
index 0fd6993..86ca660 100644
--- a/src/libsolv.ver
+++ b/src/libsolv.ver
@@ -116,6 +116,7 @@ SOLV_1.0 {
pool_trivial_installable;
pool_trivial_installable_multiversionmap;
pool_vendor2mask;
+ pool_whatmatchesdep;
queue_alloc_one;
queue_alloc_one_head;
queue_delete;
@@ -239,6 +240,7 @@ SOLV_1.0 {
selection_add;
selection_filter;
selection_make;
+ selection_make_deps;
selection_solvables;
solv_bin2hex;
solv_calloc;
diff --git a/src/pool.c b/src/pool.c
index d5a86ec..437e53d 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -1065,6 +1065,25 @@ pool_flush_namespaceproviders(Pool *pool, Id ns, Id evr)
}
}
+/* intersect dependencies in keyname with dep, return list of matching packages */
+void
+pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q)
+{
+ Id p;
+
+ queue_empty(q);
+ 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 (solvable_matchesdep(s, keyname, dep))
+ queue_push(q, p);
+ }
+}
+
/*************************************************************************/
void
diff --git a/src/pool.h b/src/pool.h
index 5527bfa..c0fdc3a 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -329,6 +329,8 @@ static inline Id *pool_whatprovides_ptr(Pool *pool, Id d)
return pool->whatprovidesdata + off;
}
+void pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q);
+
/* search the pool. the following filters are available:
* p - search just this solvable
* key - search only this key
diff --git a/src/selection.c b/src/selection.c
index b4dcadf..2e6e82d 100644
--- a/src/selection.c
+++ b/src/selection.c
@@ -573,6 +573,39 @@ selection_filelist(Pool *pool, Queue *selection, const char *name, int flags)
return SELECTION_FILELIST;
}
+static char *
+splitrel(char *rname, char *r, int *rflagsp)
+{
+ int nend = r - rname;
+ int rflags = 0;
+ if (nend && *r == '=' && r[-1] == '!')
+ {
+ nend--;
+ r++;
+ rflags = REL_LT|REL_GT;
+ }
+ for (; *r; r++)
+ {
+ if (*r == '<')
+ rflags |= REL_LT;
+ else if (*r == '=')
+ rflags |= REL_EQ;
+ else if (*r == '>')
+ rflags |= REL_GT;
+ else
+ break;
+ }
+ while (*r && (*r == ' ' || *r == '\t'))
+ r++;
+ while (nend && (rname[nend - 1] == ' ' || rname[nend - 1] == '\t'))
+ nend--;
+ if (!*rname || !*r)
+ return 0;
+ *rflagsp = rflags;
+ rname[nend] = 0;
+ return r;
+}
+
static int
selection_rel(Pool *pool, Queue *selection, const char *name, int flags)
{
@@ -586,34 +619,11 @@ selection_rel(Pool *pool, Queue *selection, const char *name, int flags)
rname = solv_strdup(name);
if ((r = strpbrk(rname, "<=>")) != 0)
{
- int nend = r - rname;
- if (nend && *r == '=' && r[-1] == '!')
+ if ((r = splitrel(rname, r, &rflags)) == 0)
{
- nend--;
- r++;
- rflags = REL_LT|REL_GT;
- }
- for (; *r; r++)
- {
- if (*r == '<')
- rflags |= REL_LT;
- else if (*r == '=')
- rflags |= REL_EQ;
- else if (*r == '>')
- rflags |= REL_GT;
- else
- break;
- }
- while (*r && (*r == ' ' || *r == '\t'))
- r++;
- while (nend && (rname[nend - 1] == ' ' || rname[nend -1 ] == '\t'))
- nend--;
- if (!*rname || !*r)
- {
solv_free(rname);
return 0;
- }
- rname[nend] = 0;
+ }
}
if ((ret = selection_depglob_arch(pool, selection, rname, flags)) != 0)
{
@@ -839,6 +849,104 @@ selection_make(Pool *pool, Queue *selection, const char *name, int flags)
return ret;
}
+static int
+matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
+{
+ if (ISRELDEP(id))
+ {
+ Reldep *rd = GETRELDEP(pool, id);
+ if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH)
+ {
+ if (matchdep(pool, rd->name, rname, rflags, revr, flags))
+ return 1;
+ if (matchdep(pool, rd->evr, rname, rflags, revr, flags))
+ return 1;
+ return 0;
+ }
+ if (rd->flags == REL_ARCH)
+ return matchdep(pool, rd->name, rname, rflags, revr, flags);
+ if (!matchdep(pool, rd->name, rname, rflags, revr, flags))
+ return 0;
+ if (rflags)
+ {
+ /* XXX: need pool_match_flags_evr here */
+ if (!pool_match_dep(pool, pool_rel2id(pool, rd->name, pool_str2id(pool, revr, 1), rflags, 1), id))
+ return 0;
+ }
+ 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;
+}
+
+/*
+ * select against the dependencies in keyname
+ * like SELECTION_REL and SELECTION_PROVIDES, but with the
+ * deps in keyname instead of provides.
+ */
+int
+selection_make_deps(Pool *pool, Queue *selection, const char *name, int flags, int keyname)
+{
+ char *rname, *r;
+ int rflags = 0;
+ Id p;
+ Queue q;
+
+ queue_empty(selection);
+ rname = solv_strdup(name);
+ if ((r = strpbrk(rname, "<=>")) != 0)
+ {
+ if ((r = splitrel(rname, r, &rflags)) == 0)
+ {
+ solv_free(rname);
+ return 0;
+ }
+ }
+ if ((flags & SELECTION_GLOB) != 0 && !strpbrk(name, "[*?") != 0)
+ flags &= ~SELECTION_GLOB;
+
+ 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_idarray(s->repo, p, keyname, &q);
+ for (i = 0; i < q.count; i++)
+ {
+ Id id = q.elements[i];
+ if (matchdep(pool, id, rname, rflags, r, flags))
+ 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;
+}
+
void
selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
{
diff --git a/src/selection.h b/src/selection.h
index 705768b..e1da169 100644
--- a/src/selection.h
+++ b/src/selection.h
@@ -34,6 +34,8 @@ extern "C" {
#define SELECTION_WITH_SOURCE (1 << 13)
extern int selection_make(Pool *pool, Queue *selection, const char *name, int flags);
+extern int selection_make_deps(Pool *pool, Queue *selection, const char *name, int flags, int keyname);
+
extern void selection_filter(Pool *pool, Queue *sel1, Queue *sel2);
extern void selection_add(Pool *pool, Queue *sel1, Queue *sel2);
extern void selection_solvables(Pool *pool, Queue *selection, Queue *pkgs);
diff --git a/src/solvable.c b/src/solvable.c
index 1633b73..b822784 100644
--- a/src/solvable.c
+++ b/src/solvable.c
@@ -856,3 +856,20 @@ solvable_unset(Solvable *s, Id keyname)
{
repo_unset(s->repo, s - s->repo->pool->solvables, keyname);
}
+
+/* return true if a dependency intersects dep in the keyname array */
+int
+solvable_matchesdep(Solvable *s, Id keyname, Id dep)
+{
+ int i;
+ Pool *pool = s->repo->pool;
+ Queue q;
+ queue_init(&q);
+ solvable_lookup_idarray(s, keyname, &q);
+ for (i = 0; i < q.count; i++)
+ if (pool_match_dep(pool, q.elements[i], dep))
+ break;
+ i = i == q.count ? 0 : 1;
+ queue_free(&q);
+ return i;
+}
diff --git a/src/solvable.h b/src/solvable.h
index ad06533..356e7d6 100644
--- a/src/solvable.h
+++ b/src/solvable.h
@@ -78,6 +78,7 @@ void solvable_unset(Solvable *s, Id keyname);
int solvable_identical(Solvable *s1, Solvable *s2);
Id solvable_selfprovidedep(Solvable *s);
+int solvable_matchesdep(Solvable *s, Id keyname, Id dep);
#ifdef __cplusplus
}