app/db-diff: assume booted deployment if less args

Very often when I have a pending deployment, I just want to find out
what the diff is before rebooting. We do print it after whatever
transaction laid down the new deployment, though we may not reboot right
away. It seems like a common enough operation to warrant some shortcuts.

This makes `db diff` more useful by automatically subbing in the booted
deployment if less arguments are given:

    rpm-ostree db diff
      <diff booted and pending deployment>
    rpm-ostree db diff $csum
      <diff booted and $csum>
    rpm-ostree db diff $csum1 $csum2
      <as before, diff $csum1 and $csum2>

As before, we never try to even load the sysroot in the last invocation,
so it still works equally well on non-OSTree systems/unprivileged.

Closes: #1294
Approved by: cgwalters
This commit is contained in:
Jonathan Lebon 2018-03-08 02:56:14 +00:00 committed by Atomic Bot
parent 2715a1b1e1
commit cdd3227f70
3 changed files with 80 additions and 15 deletions

View File

@ -137,7 +137,10 @@ Boston, MA 02111-1307, USA.
<para>
<command>diff</command> to see how the packages are
different between the trees in two commits. The
different between the trees in two revs. If no revs are
provided, the booted commit is compared to the pending
commit. If only a single rev is provided, the booted commit
is compared to that rev. The
<option>--format=diff</option> option uses
<literal>-</literal> for removed packages,
<literal>+</literal> for added packages, and finally

View File

@ -27,10 +27,12 @@
static char *opt_format = "block";
static gboolean opt_changelogs;
static char *opt_sysroot;
static GOptionEntry option_entries[] = {
{ "format", 'F', 0, G_OPTION_ARG_STRING, &opt_format, "Output format: \"diff\" or (default) \"block\"", "FORMAT" },
{ "changelogs", 'c', 0, G_OPTION_ARG_NONE, &opt_changelogs, "Also output RPM changelogs", NULL },
{ "sysroot", 0, 0, G_OPTION_ARG_STRING, &opt_sysroot, "Use system root SYSROOT (default: /)", "SYSROOT" },
{ NULL }
};
@ -96,32 +98,73 @@ rpmostree_db_builtin_diff (int argc, char **argv,
RpmOstreeCommandInvocation *invocation,
GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = g_option_context_new ("COMMIT COMMIT");
g_autoptr(GOptionContext) context = g_option_context_new ("[FROM_REV] [TO_REV]");
g_autoptr(OstreeRepo) repo = NULL;
if (!rpmostree_db_option_context_parse (context, option_entries, &argc, &argv, invocation,
&repo, cancellable, error))
return FALSE;
if (argc != 3)
if (argc > 3)
{
g_autofree char *message =
g_strdup_printf ("\"%s\" takes exactly 2 arguments", g_get_prgname ());
g_strdup_printf ("\"%s\" takes at most 2 arguments", g_get_prgname ());
rpmostree_usage_error (context, message, error);
return FALSE;
}
const char *old_ref = argv[1];
const char *old_desc = NULL;
g_autofree char *old_checksum = NULL;
if (!ostree_repo_resolve_rev (repo, old_ref, FALSE, &old_checksum, error))
return FALSE;
const char *new_ref = argv[2];
const char *new_desc = NULL;
g_autofree char *new_checksum = NULL;
if (!ostree_repo_resolve_rev (repo, new_ref, FALSE, &new_checksum, error))
return FALSE;
return print_diff (repo, old_ref, old_checksum, new_ref, new_checksum,
if (argc < 3)
{
/* find booted deployment */
const char *sysroot_path = opt_sysroot ?: "/";
g_autoptr(GFile) sysroot_file = g_file_new_for_path (sysroot_path);
g_autoptr(OstreeSysroot) sysroot = ostree_sysroot_new (sysroot_file);
if (!ostree_sysroot_load (sysroot, cancellable, error))
return FALSE;
OstreeDeployment *booted = ostree_sysroot_get_booted_deployment (sysroot);
if (!booted)
return glnx_throw (error, "Not booted into any deployment");
old_desc = "booted deployment";
old_checksum = g_strdup (ostree_deployment_get_csum (booted));
if (argc < 2)
{
/* diff booted against pending deployment */
new_desc = "pending deployment";
g_autoptr(OstreeDeployment) pending = NULL;
ostree_sysroot_query_deployments_for (sysroot, NULL, &pending, NULL);
if (!pending || ostree_deployment_equal (pending, booted))
return glnx_throw (error, "No pending deployment to diff against");
new_checksum = g_strdup (ostree_deployment_get_csum (pending));
}
else
{
/* diff against the booted deployment */
new_desc = argv[1];
if (!ostree_repo_resolve_rev (repo, new_desc, FALSE, &new_checksum, error))
return FALSE;
}
}
else
{
old_desc = argv[1];
if (!ostree_repo_resolve_rev (repo, old_desc, FALSE, &old_checksum, error))
return FALSE;
new_desc = argv[2];
if (!ostree_repo_resolve_rev (repo, new_desc, FALSE, &new_checksum, error))
return FALSE;
}
return print_diff (repo, old_desc, old_checksum, new_desc, new_checksum,
cancellable, error);
}

View File

@ -30,9 +30,16 @@ set -x
YUMREPO=/tmp/vmcheck/yumrepo/packages/x86_64
check_diff() {
from=$1; shift
to=$1; shift
vm_rpmostree db diff --format=diff $from $to > diff.txt
arg1=$1; shift
arg2=$1; shift
cmd="vm_rpmostree db diff --format=diff"
if [ -n "$arg1" ]; then
cmd="$cmd $arg1"
fi
if [ -n "$arg2" ]; then
cmd="$cmd $arg2"
fi
$cmd > diff.txt
assert_file_has_content diff.txt "$@"
}
@ -55,6 +62,18 @@ check_diff $booted_csum $pending_csum \
+pkg-to-replace \
+pkg-to-replace-archtrans
# check that it's the default behaviour without both args
check_diff "" "" \
+pkg-to-remove \
+pkg-to-replace \
+pkg-to-replace-archtrans
# check that it's the default behaviour without one arg
check_diff "$pending_csum" "" \
+pkg-to-remove \
+pkg-to-replace \
+pkg-to-replace-archtrans
# now let's make the pending csum become an update
vm_cmd ostree commit -b vmcheck --tree=ref=$pending_csum
vm_rpmostree cleanup -p