app/status: cleaner diff output for replaced pkgs

I suspect a common pattern with local replacement overrides is to
simultaneously replace a group of packages that depend on each other in
one shot, as is the case with docker, docker-common, and
docker-rhel-push-plugin currently in Fedora Atomic Host. In such cases,
we can print a cleaner diff in the status to make it easier to grok.

Before:

     ReplacedBasePackages: strace 4.18-1.fc26 -> 4.19-1.fc26, docker-common 2:1.13.1-22.gitb5e3294.fc26 -> 2:1.13.1-21.git27e468e.fc26, docker 2:1.13.1-22.gitb5e3294.fc26 -> 2:1.13.1-21.git27e468e.fc26, docker-rhel-push-plugin 2:1.13.1-22.gitb5e3294.fc26 -> 2:1.13.1-21.git27e468e.fc26

After:

     ReplacedBasePackages: docker-common docker docker-rhel-push-plugin 2:1.13.1-22.gitb5e3294.fc26 -> 2:1.13.1-21.git27e468e.fc26, strace 4.18-1.fc26 -> 4.19-1.fc26

Closes: #1004
Approved by: cgwalters
This commit is contained in:
Jonathan Lebon 2017-09-21 02:11:37 +00:00 committed by Atomic Bot
parent b7733510bd
commit c92ff926f6
4 changed files with 100 additions and 40 deletions

View File

@ -144,14 +144,15 @@ lookup_array_and_canonicalize (GVariantDict *dict,
return g_steal_pointer (&ret);
}
static char*
gv_nevra_to_evr (GVariant *gv_nevra)
static void
gv_nevra_to_evr (GString *buffer,
GVariant *gv_nevra)
{
guint64 epoch;
const char *version, *release;
g_variant_get (gv_nevra, "(sst&s&ss)", NULL, NULL, &epoch, &version, &release, NULL);
return rpmostree_custom_nevra_strdup (NULL, epoch, version, release, NULL,
PKG_NEVRA_FLAGS_EPOCH_VERSION_RELEASE);
rpmostree_custom_nevra (buffer, NULL, epoch, version, release, NULL,
PKG_NEVRA_FLAGS_EPOCH_VERSION_RELEASE);
}
/* We will have an optimized path for the case where there are just
@ -486,6 +487,10 @@ status_generic (RPMOSTreeSysroot *sysroot_proxy,
if (origin_base_local_replacements)
{
g_autoptr(GString) str = g_string_new ("");
g_autoptr(GHashTable) grouped_diffs =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify)g_ptr_array_unref);
const guint n = g_variant_n_children (origin_base_local_replacements);
for (guint i = 0; i < n; i++)
{
@ -498,25 +503,54 @@ status_generic (RPMOSTreeSysroot *sysroot_proxy,
g_variant_get_child (gv_nevra_new, 1, "&s", &name_new);
g_variant_get_child (gv_nevra_old, 1, "&s", &name_old);
if (str->len)
g_string_append (str, ", ");
/* if pkgnames match, print a nicer version like treediff */
if (g_str_equal (name_new, name_old))
{
g_autofree char *old_evr = gv_nevra_to_evr (gv_nevra_old);
g_autofree char *new_evr = gv_nevra_to_evr (gv_nevra_new);
g_string_append_printf (str, "%s %s -> %s", name_new, old_evr, new_evr);
/* let's just use str as a scratchpad to avoid excessive mallocs; the str
* needs to be stretched anyway for the final output */
gsize original_size = str->len;
gv_nevra_to_evr (str, gv_nevra_old);
g_string_append (str, " -> ");
gv_nevra_to_evr (str, gv_nevra_new);
const char *diff = str->str + original_size;
GPtrArray *pkgs = g_hash_table_lookup (grouped_diffs, diff);
if (!pkgs)
{
pkgs = g_ptr_array_new_with_free_func (g_free);
g_hash_table_insert (grouped_diffs, g_strdup (diff), pkgs);
}
g_ptr_array_add (pkgs, g_strdup (name_new));
g_string_truncate (str, original_size);
}
else
{
if (str->len)
g_string_append (str, ", ");
const char *nevra_old;
g_variant_get_child (gv_nevra_old, 0, "&s", &nevra_old);
g_string_append_printf (str, "%s -> %s", nevra_old, nevra_new);
}
g_ptr_array_add (active_replacements, g_strdup (nevra_new));
}
GLNX_HASH_TABLE_FOREACH_KV (grouped_diffs, const char*, diff, GPtrArray*, pkgs)
{
if (str->len)
g_string_append (str, ", ");
for (guint i = 0, n = pkgs->len; i < n; i++)
{
const char *pkgname = g_ptr_array_index (pkgs, i);
if (i > 0)
g_string_append_c (str, ' ');
g_string_append (str, pkgname);
}
g_string_append_c (str, ' ');
g_string_append (str, diff);
}
g_ptr_array_add (active_replacements, NULL);
if (str->len)
print_kv ("ReplacedBasePackages", max_key_len, str->str);
}

View File

@ -81,6 +81,40 @@ pkg_envra_strdup (Header h1)
return envra;
}
void
rpmostree_custom_nevra (GString *buffer,
const char *name,
uint64_t epoch,
const char *version,
const char *release,
const char *arch,
RpmOstreePkgNevraFlags flags)
{
gsize original_len = buffer->len;
if (flags & PKG_NEVRA_FLAGS_NAME)
g_string_append (buffer, name);
if (flags & (PKG_NEVRA_FLAGS_EPOCH_VERSION_RELEASE |
PKG_NEVRA_FLAGS_VERSION_RELEASE))
{
if (buffer->len > original_len)
g_string_append_c (buffer, '-');
if ((flags & PKG_NEVRA_FLAGS_EPOCH_VERSION_RELEASE) && (epoch > 0))
g_string_append_printf (buffer, "%" PRIu64 ":", epoch);
g_string_append_printf (buffer, "%s-%s", version, release);
}
if (flags & PKG_NEVRA_FLAGS_ARCH)
{
if (buffer->len > original_len)
g_string_append_c (buffer, '.');
g_string_append (buffer, arch);
}
}
char *
rpmostree_custom_nevra_strdup (const char *name,
uint64_t epoch,
@ -90,29 +124,7 @@ rpmostree_custom_nevra_strdup (const char *name,
RpmOstreePkgNevraFlags flags)
{
GString *nevra = g_string_new ("");
if (flags & PKG_NEVRA_FLAGS_NAME)
g_string_append (nevra, name);
if (flags & (PKG_NEVRA_FLAGS_EPOCH_VERSION_RELEASE |
PKG_NEVRA_FLAGS_VERSION_RELEASE))
{
if (nevra->len)
g_string_append_c (nevra, '-');
if ((flags & PKG_NEVRA_FLAGS_EPOCH_VERSION_RELEASE) && (epoch > 0))
g_string_append_printf (nevra, "%" PRIu64 ":", epoch);
g_string_append_printf (nevra, "%s-%s", version, release);
}
if (flags & PKG_NEVRA_FLAGS_ARCH)
{
if (nevra->len)
g_string_append_c (nevra, '.');
g_string_append (nevra, arch);
}
rpmostree_custom_nevra (nevra, name, epoch, version, release, arch, flags);
return g_string_free (nevra, FALSE);
}

View File

@ -143,6 +143,15 @@ typedef enum {
PKG_NEVRA_FLAGS_ARCH = (1 << 3)
} RpmOstreePkgNevraFlags;
void
rpmostree_custom_nevra (GString *buffer,
const char *name,
uint64_t epoch,
const char *version,
const char *release,
const char *arch,
RpmOstreePkgNevraFlags flags);
char *
rpmostree_custom_nevra_strdup (const char *name,
uint64_t epoch,

View File

@ -24,7 +24,7 @@ set -e
set -x
REPO=/tmp/vmcheck/yumrepo/packages/x86_64
YUMREPO=/tmp/vmcheck/yumrepo/packages/x86_64
# create a new vmcheck commit which has foo and bar in it already
@ -83,30 +83,35 @@ assert_replaced_local_pkg() {
# try to replace foo without replacing the extension
vm_build_rpm foo version 2.0
if vm_rpmostree ex override replace $REPO/foo-2.0-1.x86_64.rpm 2>err.txt; then
if vm_rpmostree ex override replace $YUMREPO/foo-2.0-1.x86_64.rpm 2>err.txt; then
assert_not_reached "successfully replaced foo without fooext?"
fi
assert_file_has_content err.txt "fooext"
echo "ok failed to replace foo without fooext"
vm_build_rpm fooext version 2.0 requires "foo = 2.0-1"
vm_rpmostree ex override replace $REPO/foo{,ext}-2.0-1.x86_64.rpm
vm_rpmostree ex override replace $YUMREPO/foo{,ext}-2.0-1.x86_64.rpm
vm_assert_status_jq \
'.deployments[0]["base-local-replacements"]|length == 2' \
'.deployments[0]["requested-base-local-replacements"]|length == 2'
assert_replaced_local_pkg foo-1.0-1.x86_64 foo-2.0-1.x86_64
assert_replaced_local_pkg fooext-1.0-1.x86_64 fooext-2.0-1.x86_64
vm_cmd rpm-ostree status > status.txt
assert_file_has_content status.txt '\(foo fooext\|fooext foo\) 1\.0-1 -> 2\.0-1'
echo "ok override replace foo and fooext"
# replace bar with older version
vm_build_rpm bar version 0.9
vm_rpmostree ex override replace $REPO/bar-0.9-1.x86_64.rpm
vm_rpmostree ex override replace $YUMREPO/bar-0.9-1.x86_64.rpm
vm_assert_status_jq \
'.deployments[0]["base-local-replacements"]|length == 3' \
'.deployments[0]["requested-base-local-replacements"]|length == 3'
assert_replaced_local_pkg foo-1.0-1.x86_64 foo-2.0-1.x86_64
assert_replaced_local_pkg fooext-1.0-1.x86_64 fooext-2.0-1.x86_64
assert_replaced_local_pkg bar-1.0-1.x86_64 bar-0.9-1.x86_64
vm_cmd rpm-ostree status > status.txt
assert_file_has_content status.txt '\(foo fooext\|fooext foo\) 1\.0-1 -> 2\.0-1'
assert_file_has_content_literal status.txt 'bar 1.0-1 -> 0.9-1'
echo "ok override replace bar"
vm_cmd ostree commit -b vmcheck --tree=ref=vmcheck
@ -138,7 +143,7 @@ vm_rpmostree cleanup -p
# test inactive replacements
vm_cmd ostree commit -b vmcheck --tree=ref=vmcheck_tmp/with_foo_and_bar
vm_rpmostree upgrade
vm_rpmostree ex override replace $REPO/bar-0.9-1.x86_64.rpm
vm_rpmostree ex override replace $YUMREPO/bar-0.9-1.x86_64.rpm
vm_assert_status_jq \
'.deployments[0]["base-local-replacements"]|length == 1' \
'.deployments[0]["requested-base-local-replacements"]|length == 1'
@ -164,8 +169,8 @@ vm_rpmostree cleanup -p
vm_build_rpm baz
vm_cmd ostree commit -b vmcheck --tree=ref=vmcheck_tmp/with_foo_and_bar
vm_rpmostree upgrade
vm_rpmostree ex override replace $REPO/bar-0.9-1.x86_64.rpm \
--install $REPO/baz-1.0-1.x86_64.rpm
vm_rpmostree ex override replace $YUMREPO/bar-0.9-1.x86_64.rpm \
--install $YUMREPO/baz-1.0-1.x86_64.rpm
vm_assert_status_jq \
'.deployments[0]["base-local-replacements"]|length == 1' \
'.deployments[0]["requested-base-local-replacements"]|length == 1' \