[Libosinfo] [osinfo-db-tools PATCH v3 3/3] import: Introduce "--latest" option

Fabiano Fidêncio fidencio at redhat.com
Thu Dec 6 15:25:42 UTC 2018


On Thu, Dec 6, 2018 at 4:01 PM Fabiano Fidêncio <fidencio at redhat.com> 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 at redhat.com>
> ---
>  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.




More information about the Libosinfo mailing list