From 8a5730525e6c80092f5c11ce255a70e1190a3dcb Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 19 Mar 2015 20:45:30 -0400 Subject: [PATCH] Add a public shared library, with "rpm -qa" for commit functionality This will help build release engineering and other types of tools; for example, rather than parsing the output of `db diff`, one should be able to call an API. Initially, this adds the generic infrastructure for a public shared library, with a new function call to do the equivalent of `rpm -qa` on a particular OSTree commit. Closes: https://github.com/projectatomic/rpm-ostree/issues/117 Closes: https://github.com/projectatomic/rpm-ostree/pull/124 --- Makefile-lib-defines.am | 24 +++++ Makefile-lib.am | 52 ++++++++++ Makefile-libutil.am | 50 ++++++++++ Makefile.am | 5 + configure.ac | 6 +- libglnx | 2 +- src/lib/rpm-ostree-1.pc.in | 11 +++ src/lib/rpmostree-db.c | 177 +++++++++++++++++++++++++++++++++++ src/lib/rpmostree-db.h | 41 ++++++++ src/lib/rpmostree.h | 23 +++++ tests/manual/test-dbquery.py | 14 +++ 11 files changed, 403 insertions(+), 2 deletions(-) create mode 100644 Makefile-lib-defines.am create mode 100644 Makefile-lib.am create mode 100644 Makefile-libutil.am create mode 100644 src/lib/rpm-ostree-1.pc.in create mode 100644 src/lib/rpmostree-db.c create mode 100644 src/lib/rpmostree-db.h create mode 100644 src/lib/rpmostree.h create mode 100644 tests/manual/test-dbquery.py diff --git a/Makefile-lib-defines.am b/Makefile-lib-defines.am new file mode 100644 index 00000000..dcd1e693 --- /dev/null +++ b/Makefile-lib-defines.am @@ -0,0 +1,24 @@ +# Shared variables between toplevel Makefile.am and doc/Makefile.am +# ...since gtk-doc forces use of recursive make =( +# +# Copyright (C) 2013 Colin Walters +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +librpmostree_public_headers = \ + src/lib/rpmostree.h \ + src/lib/rpmostree-db.h \ + $(NULL) diff --git a/Makefile-lib.am b/Makefile-lib.am new file mode 100644 index 00000000..2e09912a --- /dev/null +++ b/Makefile-lib.am @@ -0,0 +1,52 @@ +# Makefile for C source code +# +# Copyright (C) 2015 Colin Walters +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +include Makefile-lib-defines.am + +lib_LTLIBRARIES += librpmostree-1.la + +librpmostreeincludedir = $(includedir)/rpm-ostree-1 +librpmostreeinclude_HEADERS = $(librpmostree_public_headers) + +librpmostree_1_la_SOURCES = \ + src/lib/rpmostree-db.c \ + $(NULL) + +librpmostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libpriv -I$(srcdir)/src/lib \ + $(PKGDEP_RPMOSTREE_CFLAGS) +librpmostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions -export-symbols-regex '^rpm_ostree_' +librpmostree_1_la_LIBADD = libglnx.la $(PKGDEP_RPMOSTREE_LIBS) + +if BUILDOPT_INTROSPECTION +RpmOstree-1.0.gir: librpmostree-1.la Makefile +RpmOstree_1_0_gir_EXPORT_PACKAGES = rpm-ostree-1 +RpmOstree_1_0_gir_INCLUDES = OSTree-1.0 Gio-2.0 +RpmOstree_1_0_gir_CFLAGS = $(librpmostree_1_la_CFLAGS) +RpmOstree_1_0_gir_LIBS = librpmostree-1.la +RpmOstree_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=RpmOstree --symbol-prefix=rpm_ostree +RpmOstree_1_0_gir_FILES = $(librpmostreeinclude_HEADERS) $(filter-out %-private.h,$(librpmostree_1_la_SOURCES)) +INTROSPECTION_GIRS += RpmOstree-1.0.gir +gir_DATA += RpmOstree-1.0.gir +typelib_DATA += RpmOstree-1.0.typelib + +CLEANFILES += $(gir_DATA) $(typelib_DATA) +endif + +pkgconfig_DATA += src/lib/rpm-ostree-1.pc + diff --git a/Makefile-libutil.am b/Makefile-libutil.am new file mode 100644 index 00000000..3a7d5940 --- /dev/null +++ b/Makefile-libutil.am @@ -0,0 +1,50 @@ +# Makefile for C source code +# +# Copyright (C) 2015 Colin Walters +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +include Makefile-lib-defines.am + +privlib_LTLIBRARIES += librpmostreepriv.la + +librpmostree_1_la_SOURCES = \ + librpmostree-priv/rpmostree-cleanup.h \ + librpmostree-priv/rpmostree-cleanup.c \ + $(NULL) + +librpmostreepriv_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/librpmostree-priv \ + $(PKGDEP_RPMOSTREE_CFLAGS) +librpmostreepriv_la_LDFLAGS = -Bsymbolic-functions -export-symbols-regex '^rpmostreepriv_' +librpmostree_priv_la_LIBADD = libglnx.la $(PKGDEP_RPMOSTREE_LIBS) + +if BUILDOPT_INTROSPECTION +RpmOstree-1.0.gir: libostree-1.la Makefile +RpmOstree_1_0_gir_EXPORT_PACKAGES = rpm-ostree-1 +RpmOstree_1_0_gir_INCLUDES = OSTree-1 Gio-2.0 +RpmOstree_1_0_gir_CFLAGS = $(librpmostree_1_la_CFLAGS) +RpmOstree_1_0_gir_LIBS = librpmostree-1.la +RpmOstree_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=RpmOstree --symbol-prefix=rpmostree +RpmOstree_1_0_gir_FILES = $(librpmostreeinclude_HEADERS) $(filter-out %-private.h,$(librpmostree_1_la_SOURCES)) +INTROSPECTION_GIRS += RpmOstree-1.0.gir +gir_DATA += RpmOstree-1.0.gir +typelib_DATA += RpmOstree-1.0.typelib + +CLEANFILES += $(gir_DATA) $(typelib_DATA) +endif + +pkgconfig_DATA += librpmostree/rpm-ostree-1.pc + diff --git a/Makefile.am b/Makefile.am index 1d05be4a..dd0600bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,8 +33,13 @@ libglnx_srcpath := $(srcdir)/libglnx libglnx_cflags := $(PKGDEP_GIO_UNIX_CFLAGS) -I$(libglnx_srcpath) libglnx_libs := $(PKGDEP_GIO_UNIX_LIBS) +include $(INTROSPECTION_MAKEFILE) +GIRS = +TYPELIBS = $(GIRS:.gir=.typelib) + include libglnx/Makefile-libglnx.am noinst_LTLIBRARIES += libglnx.la +include Makefile-lib.am include Makefile-rpm-ostree.am include Makefile-tests.am include Makefile-man.am diff --git a/configure.ac b/configure.ac index 475669bd..b86269df 100644 --- a/configure.ac +++ b/configure.ac @@ -63,7 +63,10 @@ AC_PATH_PROG([XSLTPROC], [xsltproc]) GLIB_TESTS -GOBJECT_INTROSPECTION_REQUIRE([1.34.0]) +m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [ + GOBJECT_INTROSPECTION_CHECK([1.34.0]) +]) +AM_CONDITIONAL(BUILDOPT_INTROSPECTION, test "x$found_introspection" = xyes) AC_ARG_ENABLE(installed_tests, AS_HELP_STRING([--enable-installed-tests], @@ -91,6 +94,7 @@ if test x$enable_compose_tooling != xno; then RPM_OSTREE_FEATURES="$RPM_OSTREE_F AC_CONFIG_FILES([ Makefile +src/lib/rpm-ostree-1.pc ]) AC_OUTPUT diff --git a/libglnx b/libglnx index 376219a9..e72bbdeb 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit 376219a9c276237f21c2c5aa1f0b7875a89586b6 +Subproject commit e72bbdebb03f5d39c7f32869299ca4284786344c diff --git a/src/lib/rpm-ostree-1.pc.in b/src/lib/rpm-ostree-1.pc.in new file mode 100644 index 00000000..bc26f63d --- /dev/null +++ b/src/lib/rpm-ostree-1.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: RpmOstree +Description: Hybrid package/OSTree system +Version: @VERSION@ +Requires: ostree-1 +Libs: -L${libdir} -lrpm-ostree-1 +Cflags: -I${includedir}/ostree-1 diff --git a/src/lib/rpmostree-db.c b/src/lib/rpmostree-db.c new file mode 100644 index 00000000..505936fb --- /dev/null +++ b/src/lib/rpmostree-db.c @@ -0,0 +1,177 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2014 Colin Walters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "string.h" + +#include "rpmostree-db.h" +#include "rpmostree-cleanup.h" + +struct RpmOstreeDbQueryResult +{ + volatile gint refcount; + GPtrArray *packages; +}; + +RpmOstreeDbQueryResult * +rpm_ostree_db_query_ref (RpmOstreeDbQueryResult *result) +{ + g_atomic_int_inc (&result->refcount); + return result; +} + +void +rpm_ostree_db_query_unref (RpmOstreeDbQueryResult *result) +{ + if (!g_atomic_int_dec_and_test (&result->refcount)) + return; + + g_ptr_array_unref (result->packages); + g_free (result); +} + +G_DEFINE_BOXED_TYPE(RpmOstreeDbQueryResult, rpm_ostree_db_query_result, + rpm_ostree_db_query_ref, + rpm_ostree_db_query_unref); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(RpmOstreeDbQueryResult, rpm_ostree_db_query_unref) + +/** + * rpm_ostree_db_query_result_get_packages: + * @queryresult: Query result + * + * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): List of packages, %NULL terminated + */ +const char *const * +rpm_ostree_db_query_result_get_packages (RpmOstreeDbQueryResult *queryresult) +{ + return (const char * const *)queryresult->packages->pdata; +} + +/** + * rpm_ostree_db_query: + * @repo: An OSTree repository + * @ref: A branch name or commit + * @query: (allow-none): Currently, this must be %NULL + * @cancellable: Cancellable + * @error: Error + * + * Query the RPM packages present in the @ref branch or commit in + * @repo. At present, @query must be %NULL; all packages will be + * returned. A future enhancement to this API may allow querying a + * subset of packages. + * + * Returns: (transfer full): A new query result, or %NULL on error + */ +RpmOstreeDbQueryResult * +rpm_ostree_db_query (OstreeRepo *repo, + const char *ref, + GVariant *query, + GCancellable *cancellable, + GError **error) +{ + int rc; + OstreeRepoCheckoutOptions checkout_options = { 0, }; + g_autofree char *commit = NULL; + _cleanup_hysack_ HySack sack = NULL; + _cleanup_hyquery_ HyQuery hquery = NULL; + _cleanup_hypackagelist_ HyPackageList pkglist = NULL; + g_autofree char *tempdir = g_strdup ("/tmp/rpmostree-dbquery-XXXXXXXX"); + g_autofree char *rpmdb_tempdir = NULL; + gs_unref_object GFile* commit_rpmdb = NULL; + glnx_fd_close int tempdir_dfd = -1; + + g_return_val_if_fail (query == NULL, FALSE); + + if (!ostree_repo_resolve_rev (repo, ref, FALSE, &commit, error)) + goto out; + + if (mkdtemp (tempdir) == NULL) + { + glnx_set_error_from_errno (error); + goto out; + } + + if (!glnx_opendirat (AT_FDCWD, tempdir, FALSE, &tempdir_dfd, error)) + goto out; + + /* Create intermediate dirs */ + if (!glnx_shutil_mkdir_p_at (tempdir_dfd, "usr/share", 0777, cancellable, error)) + goto out; + + checkout_options.mode = OSTREE_REPO_CHECKOUT_MODE_USER; + checkout_options.subpath = "usr/share/rpm"; + + if (!ostree_repo_checkout_tree_at (repo, &checkout_options, + tempdir_dfd, "usr/share/rpm", + commit, + cancellable, error)) + goto out; + +#if BUILDOPT_HAWKEY_SACK_CREATE2 + sack = hy_sack_create (NULL, NULL, + rpmdb_tempdir, + NULL, + 0); +#else + sack = hy_sack_create (NULL, NULL, + rpmdb_tempdir, + 0); +#endif + if (sack == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to create sack cache"); + goto out; + } + + rc = hy_sack_load_system_repo (sack, NULL, 0); + if (!hif_error_set_from_hawkey (rc, error)) + { + g_prefix_error (error, "Failed to load system repo: "); + goto out; + } + hquery = hy_query_create (sack); + hy_query_filter (hquery, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME); + pkglist = hy_query_run (hquery); + + (void) glnx_shutil_rm_rf_at (AT_FDCWD, tempdir, cancellable, NULL); + + /* Do output creation now, no errors can be thrown */ + { + RpmOstreeDbQueryResult *result = g_new0 (RpmOstreeDbQueryResult, 1); + int i, c; + + result->refcount = 1; + result->packages = g_ptr_array_new_with_free_func (free); + + c = hy_packagelist_count (pkglist); + for (i = 0; i < c; i++) + { + HyPackage pkg = hy_packagelist_get (pkglist, i); + g_ptr_array_add (result->packages, hy_package_get_nevra (pkg)); + } + g_ptr_array_add (result->packages, NULL); + + return g_steal_pointer (&result); + } + out: + return NULL; +} diff --git a/src/lib/rpmostree-db.h b/src/lib/rpmostree-db.h new file mode 100644 index 00000000..efaf684a --- /dev/null +++ b/src/lib/rpmostree-db.h @@ -0,0 +1,41 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2015 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +typedef struct RpmOstreeDbQueryResult RpmOstreeDbQueryResult; + +GType rpm_ostree_db_query_result_get_type (void); +const char *const *rpm_ostree_db_query_result_get_packages (RpmOstreeDbQueryResult *queryresult); + +RpmOstreeDbQueryResult *rpm_ostree_db_query_ref (RpmOstreeDbQueryResult *result); +void rpm_ostree_db_query_unref (RpmOstreeDbQueryResult *result); + +RpmOstreeDbQueryResult *rpm_ostree_db_query (OstreeRepo *repo, + const char *ref, + GVariant *query, + GCancellable *cancellable, + GError **error); + +G_END_DECLS diff --git a/src/lib/rpmostree.h b/src/lib/rpmostree.h new file mode 100644 index 00000000..7ff23614 --- /dev/null +++ b/src/lib/rpmostree.h @@ -0,0 +1,23 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2015 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include diff --git a/tests/manual/test-dbquery.py b/tests/manual/test-dbquery.py new file mode 100644 index 00000000..e49dd66a --- /dev/null +++ b/tests/manual/test-dbquery.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import sys +from gi.repository import Gio, OSTree, RpmOstree + +repopath, ref = sys.argv[1:3] + +r = OSTree.Repo.new(Gio.File.new_for_path(repopath)) +r.open(None) +q = RpmOstree.db_query(r, ref, None, None) +print "Package list: " +for p in q.get_packages(): + print p +