On Thu, Dec 6, 2018 at 4:01 PM Fabiano Fidêncio <fidencio@xxxxxxxxxx> wrote: > > --latest option checks whether there's a new osinfo-db available from > the official libosinfo's release website, downloads and install it. > > The download and installation is only then when the version available in > libosinfo's release website is newer than the version installed in the > (specified location in) system. > > The file we query in order to get the "latest" available version > (https://latest.libosinfo.org) is a json that looks like: > { > "version": 1, > "database": { > "version": "20181203", > "file": "https://releases.pagure.org/libosinfo/osinfo-db-20181203.tar.xz", > "signature": "https://releases.pagure.org/libosinfo/osinfo-db-20181203.tar.xz.asc" > } > } > > The file will be automatically updated whenever a new release is done > (in a day interval). > > This commit also introduces a new dependency: json-glib, which is used > to easily manipulate the queried file's content. > > Signed-off-by: Fabiano Fidêncio <fidencio@xxxxxxxxxx> > --- > configure.ac | 1 + > tools/Makefile.am | 3 + > tools/osinfo-db-import.c | 148 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 152 insertions(+) > > diff --git a/configure.ac b/configure.ac > index 5e59568..a488a31 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -46,6 +46,7 @@ GLIB_ENCODED_VERSION="GLIB_VERSION_2_36" > PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= 2.6.0]) > PKG_CHECK_MODULES([LIBXSLT], [libxslt >= 1.0.0]) > PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.0.0]) > +PKG_CHECK_MODULES([JSON_GLIB], [json-glib-1.0]) > > PKG_CHECK_MODULES([GLIB], [glib-2.0 >= $GLIB_MINIMUM_VERSION gobject-2.0 gio-2.0]) > GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=$GLIB_ENCODED_VERSION" > diff --git a/tools/Makefile.am b/tools/Makefile.am > index f415297..e43e85d 100644 > --- a/tools/Makefile.am > +++ b/tools/Makefile.am > @@ -36,7 +36,10 @@ osinfo_db_import_SOURCES = osinfo-db-import.c $(COMMON_SOURCES) > osinfo_db_import_LDADD = $(GOBJECT_LIBS) \ > $(GIO_LIBS) \ > $(GLIB_LIBS) \ > + $(JSON_GLIB_LIBS) \ > $(LIBARCHIVE_LIBS) > +osinfo_db_import_CFLAGS = $(AM_CFLAGS) \ > + $(JSON_GLIB_CFLAGS) > > osinfo_db_export_SOURCES = osinfo-db-export.c $(COMMON_SOURCES) > osinfo_db_export_LDADD = $(GOBJECT_LIBS) \ > diff --git a/tools/osinfo-db-import.c b/tools/osinfo-db-import.c > index 77ef0b9..4c723f0 100644 > --- a/tools/osinfo-db-import.c > +++ b/tools/osinfo-db-import.c > @@ -24,12 +24,17 @@ > > #include <locale.h> > #include <glib/gi18n.h> > +#include <glib-object.h> > +#include <json-glib/json-glib.h> > #include <stdlib.h> > #include <archive.h> > #include <archive_entry.h> > > #include "osinfo-db-util.h" > > +#define LATEST_URI "https://latest.libosinfo.org" > +#define VERSION_FILE "VERSION" > + > const char *argv0; > > static int osinfo_db_import_create_reg(GFile *file, > @@ -183,6 +188,118 @@ osinfo_db_import_download_file(const gchar *url, > return ret; > } > > +static gboolean osinfo_db_get_installed_version(GFile *dir, > + gchar **version) > +{ > + GFile *file = NULL; > + GFileInfo *info = NULL; > + GFileInputStream *stream = NULL; > + goffset count; > + GError *err = NULL; > + gboolean ret = FALSE; > + > + file = g_file_get_child(dir, VERSION_FILE); > + if (file == NULL) > + return FALSE; > + > + info = g_file_query_info(file, "standard", G_FILE_QUERY_INFO_NONE, NULL, &err); > + if (err != NULL) { > + /* In the case the file was not found, it just means that there's no > + * osinfo-db installed in the specified, directory. Let's just return > + * TRUE and proceed normally from here. */ > + if (err->code == G_IO_ERROR_NOT_FOUND) { > + ret = TRUE; > + goto cleanup; > + } > + g_printerr("Failed to query info for file %s: %s\n", > + VERSION_FILE, err->message); > + goto cleanup; > + } > + > + stream = g_file_read(file, NULL, &err); > + if (err != NULL) { > + g_printerr("Failed to read the file %s: %s\n", > + VERSION_FILE, err->message); > + goto cleanup; > + } > + > + count = g_file_info_get_size(info); > + *version = g_malloc0(count*sizeof(gchar)); > + if (*version == NULL) > + goto cleanup; > + > + if (!g_input_stream_read_all(G_INPUT_STREAM(stream), > + (void *)*version, > + count, > + NULL, > + NULL, > + &err)) { > + g_printerr("Failed get the content of file %s: %s\n", > + VERSION_FILE, err->message); > + goto cleanup; > + } > + > + ret = TRUE; > + > + cleanup: > + g_object_unref(file); > + if (info != NULL) > + g_object_unref(info); > + if (stream != NULL) > + g_object_unref(stream); > + if (err != NULL) > + g_error_free(err); > + if (!ret) > + g_free(*version); > + > + return ret; > +} > + > +static gboolean osinfo_db_get_latest_info(gchar **version, > + gchar **url) > +{ > + JsonParser *parser = NULL; > + JsonReader *reader = NULL; > + GFile *uri = NULL; > + GError *err = NULL; > + gchar *content = NULL; > + gboolean ret = FALSE; > + > + uri = g_file_new_for_uri(LATEST_URI); > + if (uri == NULL) > + return FALSE; > + > + if (!g_file_load_contents(uri, NULL, &content, NULL, NULL, &err)) { > + g_printerr("Could not load the content of "LATEST_URI": %s\n", > + err->message); > + goto cleanup; > + } > + > + parser = json_parser_new(); > + json_parser_load_from_data(parser, content, -1, NULL); > + > + reader = json_reader_new(json_parser_get_root(parser)); > + > + json_reader_read_member(reader, "database"); > + json_reader_read_member(reader, "version"); > + *version = g_strdup(json_reader_get_string_value(reader)); > + json_reader_end_member(reader); > + json_reader_read_member(reader, "file"); > + *url = g_strdup(json_reader_get_string_value(reader)); > + json_reader_end_member(reader); > + json_reader_end_member(reader); > + > + ret = TRUE; > + > + cleanup: > + g_object_unref(uri); Check for parser here before calling g_object_unref() > + g_object_unref(parser); Check for reader here before calling g_object_unref() Without those two changes we may get some runtime warnings when g_file_load_contents() fails. > + g_object_unref(reader); > + g_free(content); > + > + return ret; > +} > + > static int osinfo_db_import_extract(GFile *target, > const char *source, > gboolean verbose) > @@ -279,6 +396,8 @@ gint main(gint argc, gchar **argv) > gboolean user = FALSE; > gboolean local = FALSE; > gboolean system = FALSE; > + gboolean latest = FALSE; > + gchar *latest_url = NULL; > const gchar *root = ""; > const gchar *archive = NULL; > const gchar *custom = NULL; > @@ -297,6 +416,8 @@ gint main(gint argc, gchar **argv) > N_("Import into custom directory"), NULL, }, > { "root", 0, 0, G_OPTION_ARG_STRING, &root, > N_("Installation root directory"), NULL, }, > + { "latest", 0, 0, G_OPTION_ARG_NONE, (void *)&latest, > + N_("Import the latest osinfo-db from osinfo-db's website"), NULL, }, > { NULL, 0, 0, 0, NULL, NULL, NULL }, > }; > argv0 = argv[0]; > @@ -338,6 +459,25 @@ gint main(gint argc, gchar **argv) > > archive = argc == 2 ? argv[1] : NULL; > dir = osinfo_db_get_path(root, user, local, system, custom); > + > + if (latest) { > + gchar *installed_version = NULL; > + gchar *latest_version = NULL; > + > + if (!osinfo_db_get_installed_version(dir, &installed_version)) > + goto error; installed_version has to be freed; > + > + if (!osinfo_db_get_latest_info(&latest_version, &latest_url)) > + goto error; latest_version has to be freed; > + > + if (g_strcmp0(latest_version, installed_version) <= 0) { > + ret = EXIT_SUCCESS; > + goto error; > + } > + > + archive = latest_url; > + } > + > if (osinfo_db_import_extract(dir, archive, verbose) < 0) > goto error; > > @@ -347,6 +487,7 @@ gint main(gint argc, gchar **argv) > if (dir) { > g_object_unref(dir); > } > + g_free(latest_url); > g_clear_error(&error); > g_option_context_free(context); > > @@ -430,6 +571,13 @@ Prefix the installation location with the root directory > given by C<PATH>. This is useful when wishing to install > into a chroot environment or equivalent. > > +=item B<--latest> > + > +Downloads the latest osinfo-db release from libosinfo's official > +releases website and installs it in the desired location. > +The latest osinfo-db release is only downloaded and installed > +when it's newer than the one installed in the desired location. > + > =item B<-v>, B<--verbose> > > Display verbose progress information when installing files > -- > 2.19.1 > I've fixed the issues locally already and will avoid submitting a v4 unless more changes are needed to this patch. _______________________________________________ Libosinfo mailing list Libosinfo@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libosinfo