daemon: Implement package diff methods
This commit is contained in:
parent
a140c26200
commit
075d6bdad0
@ -30,6 +30,8 @@ librpmostreed_la_SOURCES = \
|
||||
src/daemon/auth.c \
|
||||
src/daemon/deployment-utils.h \
|
||||
src/daemon/deployment-utils.c \
|
||||
src/daemon/rpmostree-package-variants.h \
|
||||
src/daemon/rpmostree-package-variants.c \
|
||||
src/daemon/os.h \
|
||||
src/daemon/os.c \
|
||||
$(NULL)
|
||||
|
@ -16,9 +16,11 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "deployment-utils.h"
|
||||
|
||||
#include "libgsystem.h"
|
||||
#include <libglnx.h>
|
||||
|
||||
char *
|
||||
deployment_generate_id (OstreeDeployment *deployment)
|
||||
@ -42,8 +44,9 @@ deployment_gpg_results (OstreeRepo *repo,
|
||||
GError *error = NULL;
|
||||
GVariant *ret = NULL;
|
||||
|
||||
gs_free gchar *remote = NULL;
|
||||
gs_unref_object OstreeGpgVerifyResult *result = NULL;
|
||||
g_autofree gchar *remote = NULL;
|
||||
glnx_unref_object OstreeGpgVerifyResult *result = NULL;
|
||||
|
||||
guint n_sigs, i;
|
||||
gboolean gpg_verify;
|
||||
GVariantBuilder builder;
|
||||
@ -87,17 +90,47 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
deployment_get_refspec (OstreeDeployment *deployment)
|
||||
{
|
||||
GKeyFile *origin = NULL; // owned by deployment
|
||||
char *origin_refspec = NULL;
|
||||
origin = ostree_deployment_get_origin (deployment);
|
||||
|
||||
if (!origin)
|
||||
goto out;
|
||||
|
||||
origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
|
||||
|
||||
out:
|
||||
return origin_refspec;
|
||||
}
|
||||
|
||||
GVariant *
|
||||
deployment_generate_blank_variant (void)
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
|
||||
g_variant_builder_add (&builder, "s", "");
|
||||
g_variant_builder_add (&builder, "s", "");
|
||||
g_variant_builder_add (&builder, "i", -1);
|
||||
g_variant_builder_add (&builder, "s", "");
|
||||
g_variant_builder_add (&builder, "s", "");
|
||||
g_variant_builder_add (&builder, "t", 0);
|
||||
g_variant_builder_add (&builder, "s", "");
|
||||
g_variant_builder_add_value (&builder, g_variant_new("av", NULL));
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
GVariant *
|
||||
deployment_generate_variant (OstreeDeployment *deployment,
|
||||
OstreeRepo *repo)
|
||||
{
|
||||
gs_unref_variant GVariant *commit = NULL;
|
||||
g_autoptr (GKeyFile) origin = NULL;
|
||||
g_autoptr (GVariant) commit = NULL;
|
||||
|
||||
gs_free gchar *origin_refspec = NULL;
|
||||
gs_free gchar *version_commit = NULL;
|
||||
gs_free gchar *id = NULL;
|
||||
g_autofree gchar *origin_refspec = NULL;
|
||||
g_autofree gchar *version_commit = NULL;
|
||||
g_autofree gchar *id = NULL;
|
||||
|
||||
GVariant *sigs = NULL; // floating variant
|
||||
GError *error = NULL;
|
||||
@ -116,7 +149,7 @@ deployment_generate_variant (OstreeDeployment *deployment,
|
||||
&commit,
|
||||
&error))
|
||||
{
|
||||
gs_unref_variant GVariant *metadata = NULL;
|
||||
g_autoptr (GVariant) metadata = NULL;
|
||||
timestamp = ostree_commit_get_timestamp (commit);
|
||||
metadata = g_variant_get_child_value (commit, 0);
|
||||
if (metadata != NULL)
|
||||
@ -128,13 +161,9 @@ deployment_generate_variant (OstreeDeployment *deployment,
|
||||
}
|
||||
g_clear_error (&error);
|
||||
|
||||
origin = ostree_deployment_get_origin (deployment);
|
||||
if (origin)
|
||||
{
|
||||
origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
|
||||
if (origin_refspec)
|
||||
sigs = deployment_gpg_results (repo, origin_refspec, csum);
|
||||
}
|
||||
origin_refspec = deployment_get_refspec (deployment);
|
||||
if (origin_refspec)
|
||||
sigs = deployment_gpg_results (repo, origin_refspec, csum);
|
||||
|
||||
if (!sigs)
|
||||
sigs = g_variant_new ("av", NULL);
|
||||
|
@ -24,5 +24,8 @@
|
||||
|
||||
char * deployment_generate_id (OstreeDeployment *deployment);
|
||||
|
||||
char * deployment_get_refspec (OstreeDeployment *deployment);
|
||||
|
||||
GVariant * deployment_generate_blank_variant (void);
|
||||
GVariant * deployment_generate_variant (OstreeDeployment *deployment,
|
||||
OstreeRepo *repo);
|
||||
|
@ -29,6 +29,8 @@ static const GDBusErrorEntry dbus_error_entries[] =
|
||||
"org.projectatomic.rpmostreed.Error.NotAuthorized"},
|
||||
{RPM_OSTREED_ERROR_UPDATE_IN_PROGRESS,
|
||||
"org.projectatomic.rpmostreed.Error.UpdateInProgress"},
|
||||
{RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
"org.projectatomic.rpmostreed.Error.InvalidRefspec"},
|
||||
};
|
||||
|
||||
GQuark
|
||||
|
@ -31,6 +31,7 @@ typedef enum {
|
||||
RPM_OSTREED_ERROR_INVALID_SYSROOT,
|
||||
RPM_OSTREED_ERROR_NOT_AUTHORIZED,
|
||||
RPM_OSTREED_ERROR_UPDATE_IN_PROGRESS,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
RPM_OSTREED_ERROR_NUM_ENTRIES,
|
||||
} RpmOstreedError;
|
||||
|
||||
|
@ -38,12 +38,18 @@
|
||||
<property name="DefaultDeployment" type="(ssisstsav)" access="read"/>
|
||||
<property name="RollbackDeployment" type="(ssisstsav)" access="read"/>
|
||||
<property name="HasCachedUpdateRpmDiff" type="b" access="read"/>
|
||||
|
||||
<!-- NONE, DIFF, PREPARE, REBOOT -->
|
||||
<property name="AutomaticUpdatePolicy" type="s" access="read"/>
|
||||
<property name="Name" type="s" access="read"/>
|
||||
|
||||
<method name="GetDeploymentsRpmDiff">
|
||||
<arg type="s" name="deployid0"/>
|
||||
<arg type="s" name="deployid1"/>
|
||||
<arg type="a(sua{sv})" name="result" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="GetCachedUpdateRpmDiff">
|
||||
<arg type="s" name="deployid"/>
|
||||
<arg type="a(sua{sv})" name="result" direction="out"/>
|
||||
</method>
|
||||
|
||||
|
396
src/daemon/os.c
396
src/daemon/os.c
@ -67,6 +67,34 @@ G_DEFINE_TYPE_WITH_CODE (OSStub, osstub, RPMOSTREE_TYPE_OS_SKELETON,
|
||||
G_IMPLEMENT_INTERFACE (RPMOSTREE_TYPE_OS,
|
||||
osstub_iface_init));
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* task_result_invoke:
|
||||
*
|
||||
* Completes a GTask where the user_data is
|
||||
* an invocation and the task data or error is
|
||||
* passed to the invocation when called back.
|
||||
*/
|
||||
static void
|
||||
task_result_invoke (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
glnx_unref_object GTask *task = G_TASK (res);
|
||||
GError *error = NULL;
|
||||
|
||||
GDBusMethodInvocation *invocation = user_data;
|
||||
|
||||
GVariant *result = g_task_propagate_pointer (task, &error);
|
||||
|
||||
if (error)
|
||||
g_dbus_method_invocation_take_error (invocation, error);
|
||||
else
|
||||
g_dbus_method_invocation_return_value (invocation, result);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
task_data_free (TaskData *data)
|
||||
{
|
||||
@ -87,7 +115,7 @@ sysroot_changed (Sysroot *sysroot,
|
||||
gpointer user_data)
|
||||
{
|
||||
OSStub *self = OSSTUB (user_data);
|
||||
g_return_val_if_fail (OSTREE_IS_SYSROOT (ot_sysroot), NULL);
|
||||
g_return_if_fail (OSTREE_IS_SYSROOT (ot_sysroot));
|
||||
|
||||
osstub_load_internals (self, ot_sysroot);
|
||||
}
|
||||
@ -199,6 +227,318 @@ out:
|
||||
return index_to_prepend;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* refspec_parse_partial:
|
||||
* @new_provided_refspec: The provided refspec
|
||||
* @base_refspec: The refspec string to base on.
|
||||
* @out_refspec: Pointer to the new refspec
|
||||
* @error: Pointer to an error pointer.
|
||||
*
|
||||
* Takes a refspec string and adds any missing bits based on the
|
||||
* base_refspec argument. Errors if a full valid refspec can't
|
||||
* be derived.
|
||||
*
|
||||
* Returns: True on sucess.
|
||||
*/
|
||||
static gboolean
|
||||
refspec_parse_partial (const gchar *new_provided_refspec,
|
||||
gchar *base_refspec,
|
||||
gchar **out_refspec,
|
||||
GError **error)
|
||||
{
|
||||
|
||||
g_autofree gchar *ref = NULL;
|
||||
g_autofree gchar *remote = NULL;
|
||||
g_autofree gchar *origin_ref = NULL;
|
||||
g_autofree gchar *origin_remote = NULL;
|
||||
GError *parse_error = NULL;
|
||||
|
||||
gboolean ret = FALSE;
|
||||
|
||||
/* Allow just switching remotes */
|
||||
if (g_str_has_suffix (new_provided_refspec, ":"))
|
||||
{
|
||||
remote = g_strdup (new_provided_refspec);
|
||||
remote[strlen (remote) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ostree_parse_refspec (new_provided_refspec, &remote,
|
||||
&ref, &parse_error))
|
||||
{
|
||||
g_set_error_literal (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
parse_error->message);
|
||||
g_clear_error (&parse_error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_refspec != NULL)
|
||||
{
|
||||
if (!ostree_parse_refspec (base_refspec, &origin_remote,
|
||||
&origin_ref, &parse_error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ref == NULL)
|
||||
{
|
||||
if (origin_ref)
|
||||
{
|
||||
ref = g_strdup (origin_ref);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
g_set_error (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
"Could not determine default ref to pull.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
else if (remote == NULL)
|
||||
{
|
||||
if (origin_remote)
|
||||
{
|
||||
remote = g_strdup (origin_remote);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
"Could not determine default remote to pull.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_strcmp0 (origin_remote, remote) == 0 &&
|
||||
g_strcmp0 (origin_ref, ref) == 0)
|
||||
{
|
||||
g_set_error (error, RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_INVALID_REFSPEC,
|
||||
"Old and new refs are equal: %s:%s",
|
||||
remote, ref);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*out_refspec = g_strconcat (remote, ":", ref, NULL);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static OstreeDeployment *
|
||||
get_deployment_for_id (OstreeSysroot *sysroot,
|
||||
const gchar *deploy_id)
|
||||
{
|
||||
g_autoptr (GPtrArray) deployments = NULL;
|
||||
guint i;
|
||||
|
||||
OstreeDeployment *deployment = NULL;
|
||||
|
||||
deployments = ostree_sysroot_get_deployments (sysroot);
|
||||
if (deployments == NULL)
|
||||
goto out;
|
||||
|
||||
for (i=0; i<deployments->len; i++)
|
||||
{
|
||||
g_autofree gchar *id = deployment_generate_id (deployments->pdata[i]);
|
||||
if (g_strcmp0 (deploy_id, id) == 0) {
|
||||
deployment = g_object_ref (deployments->pdata[i]);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return deployment;
|
||||
}
|
||||
|
||||
static void
|
||||
set_diff_task_result (GTask *task,
|
||||
GVariant *value,
|
||||
GError *error)
|
||||
{
|
||||
if (error == NULL)
|
||||
{
|
||||
g_task_return_pointer (task,
|
||||
g_variant_new ("(@a(sua{sv}))", value),
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_rebase_diff_variant_in_thread (GTask *task,
|
||||
gpointer object,
|
||||
gpointer data_ptr,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
RPMOSTreeOS *self = RPMOSTREE_OS (object);
|
||||
const gchar *name;
|
||||
|
||||
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
|
||||
glnx_unref_object OstreeRepo *ot_repo = NULL;
|
||||
glnx_unref_object OstreeDeployment *base_deployment = NULL;
|
||||
g_autofree gchar *comp_ref = NULL;
|
||||
g_autofree gchar *base_refspec = NULL;
|
||||
|
||||
GVariant *value = NULL; // freed when invoked
|
||||
GError *error = NULL; // freed when invoked
|
||||
gchar *refspec = data_ptr; // freed by task
|
||||
|
||||
if (!utils_load_sysroot_and_repo (sysroot_get_sysroot_path ( sysroot_get ()),
|
||||
cancellable,
|
||||
&ot_sysroot,
|
||||
&ot_repo,
|
||||
&error))
|
||||
goto out;
|
||||
|
||||
name = rpmostree_os_get_name (self);
|
||||
base_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);
|
||||
if (base_deployment == NULL)
|
||||
{
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No deployments found for os %s", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
base_refspec = deployment_get_refspec (base_deployment);
|
||||
if (!refspec_parse_partial (refspec,
|
||||
base_refspec,
|
||||
&comp_ref,
|
||||
&error))
|
||||
goto out;
|
||||
|
||||
value = rpm_ostree_db_diff_variant (ot_repo,
|
||||
ostree_deployment_get_csum (base_deployment),
|
||||
comp_ref,
|
||||
cancellable,
|
||||
&error);
|
||||
|
||||
out:
|
||||
set_diff_task_result (task, value, error);
|
||||
}
|
||||
|
||||
static void
|
||||
get_upgrade_diff_variant_in_thread (GTask *task,
|
||||
gpointer object,
|
||||
gpointer data_ptr,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
RPMOSTreeOS *self = RPMOSTREE_OS (object);
|
||||
const gchar *name;
|
||||
|
||||
g_autofree gchar *comp_ref = NULL;
|
||||
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
|
||||
glnx_unref_object OstreeRepo *ot_repo = NULL;
|
||||
glnx_unref_object OstreeDeployment *base_deployment = NULL;
|
||||
|
||||
GVariant *value = NULL; // freed when invoked
|
||||
GError *error = NULL; // freed when invoked
|
||||
|
||||
if (!utils_load_sysroot_and_repo (sysroot_get_sysroot_path ( sysroot_get ()),
|
||||
cancellable,
|
||||
&ot_sysroot,
|
||||
&ot_repo,
|
||||
&error))
|
||||
goto out;
|
||||
|
||||
name = rpmostree_os_get_name (self);
|
||||
base_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);
|
||||
if (base_deployment == NULL)
|
||||
{
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No deployments found for os %s", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
comp_ref = deployment_get_refspec (base_deployment);
|
||||
if (!comp_ref)
|
||||
{
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No upgrade remote found for os %s", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = rpm_ostree_db_diff_variant (ot_repo,
|
||||
ostree_deployment_get_csum (base_deployment),
|
||||
comp_ref,
|
||||
cancellable,
|
||||
&error);
|
||||
|
||||
out:
|
||||
set_diff_task_result (task, value, error);
|
||||
}
|
||||
|
||||
static void
|
||||
get_deployments_diff_variant_in_thread (GTask *task,
|
||||
gpointer object,
|
||||
gpointer data_ptr,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
const gchar *ref0;
|
||||
const gchar *ref1;
|
||||
|
||||
glnx_unref_object OstreeDeployment *deployment0 = NULL;
|
||||
glnx_unref_object OstreeDeployment *deployment1 = NULL;
|
||||
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
|
||||
glnx_unref_object OstreeRepo *ot_repo = NULL;
|
||||
|
||||
GVariant *value = NULL; // freed when invoked
|
||||
GError *error = NULL; // freed when invoked
|
||||
GPtrArray *compare_refs = data_ptr; // freed by task
|
||||
|
||||
g_return_if_fail (compare_refs->len == 2);
|
||||
|
||||
if (!utils_load_sysroot_and_repo (sysroot_get_sysroot_path ( sysroot_get ()),
|
||||
cancellable,
|
||||
&ot_sysroot,
|
||||
&ot_repo,
|
||||
&error))
|
||||
goto out;
|
||||
|
||||
deployment0 = get_deployment_for_id (ot_sysroot, compare_refs->pdata[0]);
|
||||
if (!deployment0)
|
||||
{
|
||||
gchar *id = compare_refs->pdata[0];
|
||||
g_set_error (&error,
|
||||
RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_FAILED,
|
||||
"Invalid deployment id %s",
|
||||
id);
|
||||
goto out;
|
||||
}
|
||||
ref0 = ostree_deployment_get_csum (deployment0);
|
||||
|
||||
deployment1 = get_deployment_for_id (ot_sysroot, compare_refs->pdata[1]);
|
||||
if (!deployment1)
|
||||
{
|
||||
gchar *id = compare_refs->pdata[1];
|
||||
g_set_error (&error,
|
||||
RPM_OSTREED_ERROR,
|
||||
RPM_OSTREED_ERROR_FAILED,
|
||||
"Invalid deployment id %s",
|
||||
id);
|
||||
goto out;
|
||||
}
|
||||
ref1 = ostree_deployment_get_csum (deployment1);
|
||||
|
||||
value = rpm_ostree_db_diff_variant (ot_repo,
|
||||
ref0,
|
||||
ref1,
|
||||
cancellable,
|
||||
&error);
|
||||
|
||||
out:
|
||||
set_diff_task_result (task, value, error);
|
||||
}
|
||||
|
||||
static void
|
||||
osstub_upgrade_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
@ -282,12 +622,47 @@ osstub_transaction_complete (GObject *source_object,
|
||||
g_clear_error (&local_error);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
handle_get_deployments_rpm_diff (RPMOSTreeOS *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const char *arg_deployid0,
|
||||
const char *arg_deployid1)
|
||||
{
|
||||
OSStub *self = OSSTUB (interface);
|
||||
GPtrArray *compare_refs = NULL; // freed by task
|
||||
GTask *task = NULL;
|
||||
|
||||
glnx_unref_object GCancellable *cancellable = NULL;
|
||||
|
||||
compare_refs = g_ptr_array_new_with_free_func (g_free);
|
||||
g_ptr_array_add (compare_refs, g_strdup (arg_deployid0));
|
||||
g_ptr_array_add (compare_refs, g_strdup (arg_deployid1));
|
||||
|
||||
task = g_task_new (self, cancellable,
|
||||
task_result_invoke,
|
||||
invocation);
|
||||
g_task_set_task_data (task,
|
||||
compare_refs,
|
||||
(GDestroyNotify) g_ptr_array_unref);
|
||||
g_task_run_in_thread (task, get_deployments_diff_variant_in_thread);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
osstub_handle_get_cached_update_rpm_diff (RPMOSTreeOS *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const char *arg_deployid)
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
/* FIXME */
|
||||
OSStub *self = OSSTUB (interface);
|
||||
GTask *task = NULL;
|
||||
|
||||
glnx_unref_object GCancellable *cancellable = NULL;
|
||||
|
||||
task = g_task_new (self, cancellable,
|
||||
task_result_invoke,
|
||||
invocation);
|
||||
g_task_run_in_thread (task, get_upgrade_diff_variant_in_thread);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -476,7 +851,18 @@ osstub_handle_get_cached_rebase_rpm_diff (RPMOSTreeOS *interface,
|
||||
const char *arg_refspec,
|
||||
const char * const *arg_packages)
|
||||
{
|
||||
/* FIXME */
|
||||
OSStub *self = OSSTUB (interface);
|
||||
GTask *task = NULL;
|
||||
glnx_unref_object GCancellable *cancellable = NULL;
|
||||
|
||||
/* TODO: Totally ignoring packages for now */
|
||||
task = g_task_new (self, cancellable,
|
||||
task_result_invoke,
|
||||
invocation);
|
||||
g_task_set_task_data (task,
|
||||
g_strdup (arg_refspec),
|
||||
g_free);
|
||||
g_task_run_in_thread (task, get_rebase_diff_variant_in_thread);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
213
src/daemon/rpmostree-package-variants.c
Normal file
213
src/daemon/rpmostree-package-variants.c
Normal file
@ -0,0 +1,213 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <rpmostree.h>
|
||||
#include "rpmostree-package-variants.h"
|
||||
#include <libglnx.h>
|
||||
|
||||
static GVariant *
|
||||
build_diff_variant (const gchar *name,
|
||||
guint type,
|
||||
RpmOstreePackage *old_package,
|
||||
RpmOstreePackage *new_package)
|
||||
{
|
||||
GVariantBuilder options_builder;
|
||||
GVariantBuilder builder;
|
||||
g_variant_builder_init (&options_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
|
||||
if (old_package)
|
||||
{
|
||||
g_variant_builder_add (&options_builder, "{sv}", "PreviousPackage",
|
||||
rpm_ostree_package_to_variant (old_package));
|
||||
}
|
||||
|
||||
if (new_package)
|
||||
{
|
||||
g_variant_builder_add (&options_builder, "{sv}", "NewPackage",
|
||||
rpm_ostree_package_to_variant (new_package));
|
||||
}
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
|
||||
g_variant_builder_add (&builder, "s", name);
|
||||
g_variant_builder_add (&builder, "u", type);
|
||||
g_variant_builder_add_value (&builder, g_variant_builder_end (&options_builder));
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rpm_ostree_package_to_variant
|
||||
* @package: RpmOstreePackage
|
||||
*
|
||||
* Returns: A GVariant of (sss) where values are
|
||||
* (package name, evr, arch)
|
||||
*/
|
||||
GVariant *
|
||||
rpm_ostree_package_to_variant (RpmOstreePackage *package)
|
||||
{
|
||||
return g_variant_new ("(sss)",
|
||||
rpm_ostree_package_get_name (package),
|
||||
rpm_ostree_package_get_evr (package),
|
||||
rpm_ostree_package_get_arch (package));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rpm_ostree_db_diff_variant_compare_by_name (const void *v1,
|
||||
const void *v2)
|
||||
|
||||
{
|
||||
GVariant **v1pp = (GVariant**)v1;
|
||||
GVariant *variant1 = *v1pp;
|
||||
GVariant **v2pp = (GVariant**)v2;
|
||||
GVariant *variant2 = *v2pp;
|
||||
|
||||
gchar *name1 = NULL;
|
||||
gchar *name2 = NULL;
|
||||
g_variant_get_child (variant1, 0, "&s", &name1);
|
||||
g_variant_get_child (variant2, 0, "&s", &name2);
|
||||
|
||||
return g_strcmp0 (name1, name2);
|
||||
}
|
||||
|
||||
int
|
||||
rpm_ostree_db_diff_variant_compare_by_type (const void *v1,
|
||||
const void *v2)
|
||||
|
||||
{
|
||||
GVariant **v1pp = (GVariant**)v1;
|
||||
GVariant *variant1 = *v1pp;
|
||||
GVariant **v2pp = (GVariant**)v2;
|
||||
GVariant *variant2 = *v2pp;
|
||||
|
||||
guint type1;
|
||||
guint type2;
|
||||
|
||||
g_variant_get_child (variant1, 1, "u", &type1);
|
||||
g_variant_get_child (variant2, 1, "u", &type2);
|
||||
|
||||
if (type1 == type2)
|
||||
return rpm_ostree_db_diff_variant_compare_by_name (v1, v2);
|
||||
|
||||
return type1 - type2;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpm_ostree_db_build_diff_variant
|
||||
* @repo: A OstreeRepo
|
||||
* @old_ref: old ref to use
|
||||
* @new_ref: New ref to use
|
||||
* GCancellable: *cancellable
|
||||
* GError: **error
|
||||
*
|
||||
* Returns: A GVariant that represents the differences
|
||||
* between the rpm databases on the given refs.
|
||||
*/
|
||||
GVariant *
|
||||
rpm_ostree_db_diff_variant (OstreeRepo *repo,
|
||||
const char *from_rev,
|
||||
const char *to_rev,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GVariant *variant = NULL;
|
||||
GVariantBuilder builder;
|
||||
|
||||
g_autoptr (GPtrArray) removed = NULL;
|
||||
g_autoptr (GPtrArray) added = NULL;
|
||||
g_autoptr (GPtrArray) modified_old = NULL;
|
||||
g_autoptr (GPtrArray) modified_new = NULL;
|
||||
g_autoptr (GPtrArray) found = NULL;
|
||||
|
||||
guint i;
|
||||
|
||||
found = g_ptr_array_new ();
|
||||
|
||||
if (!rpm_ostree_db_diff (repo, from_rev, to_rev,
|
||||
&removed, &added, &modified_old,
|
||||
&modified_new, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (modified_old->len > 0)
|
||||
{
|
||||
for (i = 0; i < modified_old->len; i++)
|
||||
{
|
||||
guint type = RPM_OSTREE_PACKAGE_UPGRADED;
|
||||
RpmOstreePackage *oldpkg = modified_old->pdata[i];
|
||||
RpmOstreePackage *newpkg;
|
||||
|
||||
const char *name = rpm_ostree_package_get_name (oldpkg);
|
||||
g_assert_cmpuint (i, <, modified_new->len);
|
||||
newpkg = modified_new->pdata[i];
|
||||
|
||||
if (rpm_ostree_package_cmp (oldpkg, newpkg) > 0)
|
||||
type = RPM_OSTREE_PACKAGE_DOWNGRADED;
|
||||
|
||||
g_ptr_array_add (found,
|
||||
build_diff_variant (name, type, oldpkg, newpkg));
|
||||
}
|
||||
}
|
||||
|
||||
if (removed->len > 0)
|
||||
{
|
||||
for (i = 0; i < removed->len; i++)
|
||||
{
|
||||
RpmOstreePackage *pkg = removed->pdata[i];
|
||||
const char *name = rpm_ostree_package_get_name (pkg);
|
||||
g_ptr_array_add (found,
|
||||
build_diff_variant (name,
|
||||
RPM_OSTREE_PACKAGE_REMOVED,
|
||||
pkg,
|
||||
NULL));
|
||||
}
|
||||
}
|
||||
|
||||
if (added->len > 0)
|
||||
{
|
||||
for (i = 0; i < added->len; i++)
|
||||
{
|
||||
RpmOstreePackage *pkg = added->pdata[i];
|
||||
const char *name = rpm_ostree_package_get_name (pkg);
|
||||
g_ptr_array_add (found,
|
||||
build_diff_variant (name,
|
||||
RPM_OSTREE_PACKAGE_ADDED,
|
||||
NULL,
|
||||
pkg));
|
||||
}
|
||||
}
|
||||
|
||||
g_ptr_array_sort (found, rpm_ostree_db_diff_variant_compare_by_type);
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
|
||||
for (i = 0; i < found->len; i++)
|
||||
{
|
||||
GVariant *v = found->pdata[i];
|
||||
g_variant_builder_add_value (&builder, v);
|
||||
}
|
||||
|
||||
if (found->len > 1)
|
||||
variant = g_variant_builder_end (&builder);
|
||||
else
|
||||
variant = g_variant_new ("a(sua{sv})", NULL);
|
||||
|
||||
out:
|
||||
return variant;
|
||||
}
|
48
src/daemon/rpmostree-package-variants.h
Normal file
48
src/daemon/rpmostree-package-variants.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- 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 <ostree.h>
|
||||
#include <rpmostree.h>
|
||||
|
||||
typedef enum {
|
||||
RPM_OSTREE_PACKAGE_ADDED,
|
||||
RPM_OSTREE_PACKAGE_REMOVED,
|
||||
RPM_OSTREE_PACKAGE_UPGRADED,
|
||||
RPM_OSTREE_PACKAGE_DOWNGRADED
|
||||
} RpmOstreePackageDiffTypes;
|
||||
|
||||
|
||||
GVariant * rpm_ostree_db_diff_variant (OstreeRepo *repo,
|
||||
const char *from_ref,
|
||||
const char *to_ref,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
int rpm_ostree_db_diff_variant_compare_by_name (const void *v1,
|
||||
const void *v2);
|
||||
|
||||
int rpm_ostree_db_diff_variant_compare_by_type (const void *v1,
|
||||
const void *v2);
|
||||
|
||||
|
||||
_RPMOSTREE_EXTERN
|
||||
GVariant * rpm_ostree_package_to_variant (RpmOstreePackage *package);
|
Loading…
Reference in New Issue
Block a user