From 97c831dd5fe509483939cdd40703a0ce8e0e9bfd Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 24 Oct 2019 15:21:49 -0600 Subject: [PATCH] bin/show: Add --print-sizes option to show sizes metadata Use the new `ostree_commit_get_object_sizes()` API to read the `ostree.sizes` commit metadata and print a summary. --- Makefile-tests.am | 1 + bash/ostree | 1 + man/ostree-show.xml | 11 ++++++ src/ostree/ot-builtin-show.c | 69 ++++++++++++++++++++++++++++++++++++ tests/test-pull-sizes.sh | 58 ++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100755 tests/test-pull-sizes.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index a4acb8e0..615b8480 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -86,6 +86,7 @@ _installed_or_uninstalled_test_scripts = \ tests/test-pull-resume.sh \ tests/test-pull-basicauth.sh \ tests/test-pull-repeated.sh \ + tests/test-pull-sizes.sh \ tests/test-pull-untrusted.sh \ tests/test-pull-override-url.sh \ tests/test-pull-localcache.sh \ diff --git a/bash/ostree b/bash/ostree index fc429983..4aec588b 100644 --- a/bash/ostree +++ b/bash/ostree @@ -1445,6 +1445,7 @@ _ostree_show() { local boolean_options=" $main_boolean_options --print-related + --print-sizes --raw " diff --git a/man/ostree-show.xml b/man/ostree-show.xml index a3d9aa4a..a28f704c 100644 --- a/man/ostree-show.xml +++ b/man/ostree-show.xml @@ -99,6 +99,17 @@ Boston, MA 02111-1307, USA. + + + + + Show the commit size metadata. This in only supported for + commits that contain ostree.sizes + metadata. This can be included when creating commits with + ostree commit --generate-sizes. + + + diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index 5091a93c..96e2d4c6 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -33,6 +33,7 @@ static gboolean opt_print_related; static char* opt_print_variant_type; static char* opt_print_metadata_key; static char* opt_print_detached_metadata_key; +static gboolean opt_print_sizes; static gboolean opt_raw; static gboolean opt_no_byteswap; static char *opt_gpg_homedir; @@ -48,6 +49,7 @@ static GOptionEntry options[] = { { "print-variant-type", 0, 0, G_OPTION_ARG_STRING, &opt_print_variant_type, "Memory map OBJECT (in this case a filename) to the GVariant type string", "TYPE" }, { "print-metadata-key", 0, 0, G_OPTION_ARG_STRING, &opt_print_metadata_key, "Print string value of metadata key", "KEY" }, { "print-detached-metadata-key", 0, 0, G_OPTION_ARG_STRING, &opt_print_detached_metadata_key, "Print string value of detached metadata key", "KEY" }, + { "print-sizes", 0, 0, G_OPTION_ARG_NONE, &opt_print_sizes, "Show the commit size metadata", NULL }, { "raw", 0, 0, G_OPTION_ARG_NONE, &opt_raw, "Show raw variant data" }, { "no-byteswap", 'B', 0, G_OPTION_ARG_NONE, &opt_no_byteswap, "Do not automatically convert variant data from big endian" }, { "gpg-homedir", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"}, @@ -146,6 +148,65 @@ do_print_metadata_key (OstreeRepo *repo, return TRUE; } +static gboolean +do_print_sizes (OstreeRepo *repo, + const char *rev, + GError **error) +{ + g_autoptr(GVariant) commit = NULL; + if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, rev, + &commit, error)) + { + g_prefix_error (error, "Failed to read commit: "); + return FALSE; + } + + g_autoptr(GPtrArray) sizes = NULL; + if (!ostree_commit_get_object_sizes (commit, &sizes, error)) + return FALSE; + + gint64 new_archived = 0; + gint64 new_unpacked = 0; + gsize new_objects = 0; + gint64 archived = 0; + gint64 unpacked = 0; + gsize objects = 0; + for (guint i = 0; i < sizes->len; i++) + { + OstreeCommitSizesEntry *entry = sizes->pdata[i]; + + archived += entry->archived; + unpacked += entry->unpacked; + objects++; + + gboolean exists; + if (!ostree_repo_has_object (repo, entry->objtype, entry->checksum, + &exists, NULL, error)) + return FALSE; + + if (!exists) + { + /* Object not in local repo */ + new_archived += entry->archived; + new_unpacked += entry->unpacked; + new_objects++; + } + } + + g_autofree char *new_archived_str = g_format_size (new_archived); + g_autofree char *archived_str = g_format_size (archived); + g_autofree char *new_unpacked_str = g_format_size (new_unpacked); + g_autofree char *unpacked_str = g_format_size (unpacked); + g_print ("Compressed size (needed/total): %s/%s\n" + "Unpacked size (needed/total): %s/%s\n" + "Number of objects (needed/total): %" G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT "\n", + new_archived_str, archived_str, + new_unpacked_str, unpacked_str, + new_objects, objects); + + return TRUE; +} + static gboolean print_object (OstreeRepo *repo, OstreeObjectType objtype, @@ -279,6 +340,14 @@ ostree_builtin_show (int argc, char **argv, OstreeCommandInvocation *invocation, if (!do_print_variant_generic (G_VARIANT_TYPE (opt_print_variant_type), rev, error)) return FALSE; } + else if (opt_print_sizes) + { + if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error)) + return FALSE; + + if (!do_print_sizes (repo, resolved_rev, error)) + return FALSE; + } else { gboolean found = FALSE; diff --git a/tests/test-pull-sizes.sh b/tests/test-pull-sizes.sh new file mode 100755 index 00000000..8ee07cc8 --- /dev/null +++ b/tests/test-pull-sizes.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# +# Copyright (C) 2019 Endless Mobile, Inc. +# +# SPDX-License-Identifier: LGPL-2.0+ +# +# This library 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 License, 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. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +setup_fake_remote_repo1 "archive" "--generate-sizes" + +echo '1..3' + +cd ${test_tmpdir} +mkdir repo +ostree_repo_init repo +${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo + +# Pull commit metadata only. All size and objects will be needed. +${CMD_PREFIX} ostree --repo=repo pull --commit-metadata-only origin main +${CMD_PREFIX} ostree --repo=repo show --print-sizes origin:main > show.txt +assert_file_has_content show.txt 'Compressed size (needed/total): 637[  ]bytes/637[  ]bytes' +assert_file_has_content show.txt 'Unpacked size (needed/total): 457[  ]bytes/457[  ]bytes' +assert_file_has_content show.txt 'Number of objects (needed/total): 10/10' +echo "ok sizes commit metadata only" + +# Pull the parent commit so we get most of the objects +parent=$(${CMD_PREFIX} ostree --repo=repo rev-parse origin:main^) +${CMD_PREFIX} ostree --repo=repo pull origin ${parent} +${CMD_PREFIX} ostree --repo=repo show --print-sizes origin:main > show.txt +assert_file_has_content show.txt 'Compressed size (needed/total): 501[  ]bytes/637[  ]bytes' +assert_file_has_content show.txt 'Unpacked size (needed/total): 429[  ]bytes/457[  ]bytes' +assert_file_has_content show.txt 'Number of objects (needed/total): 6/10' +echo "ok sizes commit partial" + +# Finish pulling the commit and check that no objects needed +${CMD_PREFIX} ostree --repo=repo pull origin main +${CMD_PREFIX} ostree --repo=repo show --print-sizes origin:main > show.txt +assert_file_has_content show.txt 'Compressed size (needed/total): 0[  ]bytes/637[  ]bytes' +assert_file_has_content show.txt 'Unpacked size (needed/total): 0[  ]bytes/457[  ]bytes' +assert_file_has_content show.txt 'Number of objects (needed/total): 0/10' +echo "ok sizes commit full"