libpriv/core: also checksum package action

When calculating the goal checksum, we only accounted for package
installs. But with override support, there are now other package actions
we need to pick up on.

In practice, the fact that we also checksum the treespec made this hard
to actually cause an issue. Although, since the actual final goal is
also dependent on the underlying rpmdb, I can imagine e.g. a replacement
override be considered a `DNF_PACKAGE_INFO_UPDATE` for one rpmdb appear
as a `DNF_PACKAGE_INFO_DOWNGRADE` for another.

While we're here, do some light code style porting and streamline the
checksumming process to avoid creating a separate `GPtrArray`.

Closes: #1053
Approved by: cgwalters
This commit is contained in:
Jonathan Lebon 2017-10-13 13:20:10 +00:00 committed by Atomic Bot
parent e5e9f1f0b8
commit 2b4a65bca5
2 changed files with 56 additions and 30 deletions

View File

@ -1612,42 +1612,65 @@ rpmostree_context_prepare (RpmOstreeContext *self,
return TRUE;
}
/* Generate a checksum from a goal in a repeatable fashion -
* we checksum an ordered array of the checksums of individual
* packages. We *used* to just checksum the NEVRAs but that
* breaks with RPM gpg signatures.
static int
compare_pkgs (gconstpointer ap,
gconstpointer bp)
{
DnfPackage **a = (gpointer)ap;
DnfPackage **b = (gpointer)bp;
return dnf_package_cmp (*a, *b);
}
/* XXX: push this into libdnf */
static const char*
convert_dnf_action_to_string (DnfStateAction action)
{
switch (action)
{
case DNF_STATE_ACTION_INSTALL:
return "install";
case DNF_STATE_ACTION_UPDATE:
return "update";
case DNF_STATE_ACTION_DOWNGRADE:
return "downgrade";
case DNF_STATE_ACTION_REMOVE:
return "remove";
case DNF_STATE_ACTION_OBSOLETE:
return "obsolete";
default:
g_assert_not_reached ();
}
return NULL; /* satisfy static analysis tools */
}
/* Generate a checksum from a goal in a repeatable fashion - we checksum an ordered array of
* the checksums of individual packages as well as the associated action. We *used* to just
* checksum the NEVRAs but that breaks with RPM gpg signatures.
*
* This can be used to efficiently see if the goal has changed from a
* previous one.
*
* It can also handle goals in which only dummy header-only pkgs are
* available. In such cases, it uses the ostree checksum of the pkg
* instead.
* This can be used to efficiently see if the goal has changed from a previous one.
*/
void
rpmostree_dnf_add_checksum_goal (GChecksum *checksum,
HyGoal goal)
{
g_autoptr(GPtrArray) pkglist = NULL;
guint i;
g_autoptr(GPtrArray) pkg_checksums = g_ptr_array_new_with_free_func (g_free);
pkglist = hy_goal_list_installs (goal, NULL);
g_autoptr(GPtrArray) pkglist = dnf_goal_get_packages (goal, DNF_PACKAGE_INFO_INSTALL,
DNF_PACKAGE_INFO_UPDATE,
DNF_PACKAGE_INFO_DOWNGRADE,
DNF_PACKAGE_INFO_REMOVE,
DNF_PACKAGE_INFO_OBSOLETE,
-1);
g_assert (pkglist);
for (i = 0; i < pkglist->len; i++)
g_ptr_array_sort (pkglist, compare_pkgs);
for (guint i = 0; i < pkglist->len; i++)
{
DnfPackage *pkg = pkglist->pdata[i];
DnfStateAction action = dnf_package_get_action (pkg);
const char *action_str = convert_dnf_action_to_string (action);
g_checksum_update (checksum, (guint8*)action_str, strlen (action_str));
g_autofree char* chksum_repr = NULL;
g_assert (rpmostree_get_repodata_chksum_repr (pkg, &chksum_repr, NULL));
g_ptr_array_add (pkg_checksums, g_steal_pointer (&chksum_repr));
}
g_ptr_array_sort (pkg_checksums, rpmostree_ptrarray_sort_compare_strings);
for (guint i = 0; i < pkg_checksums->len; i++)
{
const char *pkg_checksum = pkg_checksums->pdata[i];
g_checksum_update (checksum, (guint8*)pkg_checksum, strlen (pkg_checksum));
g_checksum_update (checksum, (guint8*)chksum_repr, strlen (chksum_repr));
}
}

View File

@ -961,8 +961,8 @@ rpmostree_print_transaction (DnfContext *hifctx)
{ g_autoptr(GPtrArray) packages = NULL;
packages = dnf_goal_get_packages (dnf_context_get_goal (hifctx),
DNF_PACKAGE_INFO_REMOVE,
DNF_PACKAGE_INFO_OBSOLETE,
DNF_PACKAGE_INFO_REMOVE,
DNF_PACKAGE_INFO_OBSOLETE,
-1);
if (packages->len > 0)
@ -1058,13 +1058,16 @@ rpmostree_get_repodata_chksum_repr (DnfPackage *pkg,
g_autofree char *chksum = NULL;
const unsigned char *chksum_raw = NULL;
chksum_raw = dnf_package_get_chksum (pkg, &chksum_type);
/* for rpmdb packages, use the hdr checksum */
if (dnf_package_installed (pkg))
chksum_raw = dnf_package_get_hdr_chksum (pkg, &chksum_type);
else
chksum_raw = dnf_package_get_chksum (pkg, &chksum_type);
if (chksum_raw)
chksum = hy_chksum_str (chksum_raw, chksum_type);
if (chksum == NULL)
return glnx_throw (error, "Couldn't get chksum for pkg %s",
dnf_package_get_nevra(pkg));
return glnx_throw (error, "Couldn't get chksum for pkg %s", dnf_package_get_nevra(pkg));
*out_chksum_repr =
g_strconcat (hy_chksum_name (chksum_type), ":", chksum, NULL);