Skip to content

Instantly share code, notes, and snippets.

@ignatenkobrain
Created July 21, 2019 22:14
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ignatenkobrain/a2b21a4db497a2a4b441e3957fcc8483 to your computer and use it in GitHub Desktop.
Save ignatenkobrain/a2b21a4db497a2a4b441e3957fcc8483 to your computer and use it in GitHub Desktop.
#include <locale.h>
#include <stdlib.h>
#include <libsmartcols.h>
#include <solv/policy.h>
#include <solv/pool.h>
#include <solv/poolarch.h>
#include <solv/repo.h>
#include <solv/repo_solv.h>
#include <solv/selection.h>
#include <solv/util.h>
static inline Solvable *
get_first_best_solvable(Pool *pool, Queue *sel)
{
if (!sel->count)
return NULL;
Queue q;
queue_init(&q);
selection_solvables(pool, sel, &q);
pool_best_solvables(pool, &q, 0);
Solvable *s = pool_id2solvable(pool, q.elements[0]);
queue_free(&q);
return s;
}
static inline Solvable *
get_sourcepkg(Solvable *p)
{
if (p->arch == ARCH_SRC || p->arch == ARCH_NOSRC)
return p;
Pool *pool = p->repo->pool;
const char *srcpkg = solvable_lookup_sourcepkg(p);
int l = strlen(srcpkg) - 4;
char *source = solv_malloc(l + 1);
strncpy(source, srcpkg, l);
source[l] = '\0';
Queue sel;
queue_init(&sel);
selection_make(pool, &sel, source, SELECTION_CANON | SELECTION_WITH_SOURCE);
Solvable *s = get_first_best_solvable(pool, &sel);
solv_free(source);
queue_free(&sel);
return s;
}
int
main(int argc, char **argv)
{
Queue sel, pkgs, q;
Id p;
int r = EXIT_FAILURE;
Pool *pool = pool_create();
pool_setarchpolicy(pool, "x86_64"); /* TODO: replace by auto-arch detect. */
enum { COL_PKG, COL_DEP, COL_INFO };
static const char *repo_names[] = {
"rawhide",
"rawhide-source",
NULL
};
for (const char **repo_name = repo_names; *repo_name; repo_name++)
{
Repo *repo = repo_create(pool, *repo_name);
const char *path = pool_tmpjoin(pool, "/var/cache/dnf/", *repo_name, ".solv");
FILE *fp = fopen(path, "rb");
repo_add_solv(repo, fp, 0);
fclose(fp);
}
pool_addfileprovides(pool);
pool_createwhatprovides(pool);
setlocale(LC_ALL, "");
queue_init(&sel);
selection_make(pool, &sel, argv[1], SELECTION_NAME | SELECTION_WITH_SOURCE);
if (!sel.count)
{
fprintf(stderr, "Could not find package with name '%s'.\n", argv[1]);
goto exit;
}
Solvable *pkg = get_first_best_solvable(pool, &sel);
Solvable *spkg = get_sourcepkg(pkg);
if (!spkg)
{
fprintf(stderr, "Could not find source package for '%s'.\n", pool_solvable2str(pool, pkg));
goto exit;
}
struct libscols_table *tb = scols_new_table();
scols_table_new_column(tb, "PACKAGE", 0, SCOLS_FL_NOEXTREMES);
scols_table_new_column(tb, "DEPENDENT", 0, 0);
scols_table_new_column(tb, "DEPENDENCIES", 0, 0);
struct libscols_cell *title = scols_table_get_title(tb);
scols_cell_set_data(title, pool_solvable2str(pool, spkg));
scols_cell_set_flags(title, SCOLS_CELL_FL_CENTER);
struct libscols_symbols *sy = scols_new_symbols();
scols_symbols_set_title_padding(sy, "=");
scols_table_set_symbols(tb, sy);
queue_init(&pkgs);
queue_init(&q);
char *sourcepkg = solv_dupjoin(pool_solvable2str(pool, spkg), ".rpm", NULL);
FOR_POOL_SOLVABLES (p)
{
Solvable *s = pool_id2solvable(pool, p);
/* We are interested in packages whose SOURCERPM match our source RPM. */
if (!pool_installable(pool, s) || strcmp(solvable_lookup_sourcepkg(s), sourcepkg))
continue;
struct libscols_line *ln = scols_table_new_line(tb, NULL);
scols_line_set_data(ln, COL_PKG, pool_solvable2str(pool, s));
struct libscols_line *xln = ln;
queue_empty(&sel);
selection_make_matchsolvable(pool, &sel, p, SELECTION_WITH_SOURCE, SOLVABLE_REQUIRES, 0);
/* Nothing depends on this package. */
if (!sel.count)
continue;
queue_empty(&pkgs);
selection_solvables(pool, &sel, &pkgs);
for (int i = 0; i < pkgs.count; i++)
{
Id pp = pkgs.elements[i];
Solvable *ss = pool_id2solvable(pool, pp);
/* Package from the same source. */
const char *ssource = solvable_lookup_sourcepkg(ss);
if (ssource && !strcmp(ssource, sourcepkg))
continue;
if (!xln)
xln = scols_table_new_line(tb, NULL);
scols_line_set_data(xln, COL_DEP, pool_solvable2str(pool, ss));
queue_empty(&q);
solvable_lookup_deparray(ss, SOLVABLE_REQUIRES, &q, 0);
for (int j = 0; j < q.count; j++)
{
Id dep = q.elements[j];
queue_empty(&sel);
queue_push2(&sel, SOLVER_SOLVABLE, p);
selection_make_matchdepid(pool, &sel, dep, SELECTION_FILTER | SELECTION_WITH_SOURCE, SOLVABLE_PROVIDES, 0);
/* This dependency is not the one. */
if (!sel.count)
continue;
if (!xln)
xln = scols_table_new_line(tb, NULL);
scols_line_set_data(xln, COL_INFO, pool_dep2str(pool, dep));
xln = NULL;
}
xln = NULL;
}
}
solv_free(sourcepkg);
scols_print_table(tb);
scols_unref_table(tb);
r = EXIT_SUCCESS;
exit:
pool_free(pool);
return r;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment