Add a "rebase" builtin

This is exactly the code from "ostree admin switch", except it's
called "rebase" because in the future it will also carry along any
locally layered packages.
This commit is contained in:
Colin Walters 2014-05-29 18:00:11 -04:00
parent 7ba1a9b46f
commit 976c68542b
8 changed files with 289 additions and 51 deletions

View File

@ -24,6 +24,8 @@ noinst_LTLIBRARIES += librpmostree.la
librpmostree_la_SOURCES = \
src/rpmostree-postprocess.c \
src/rpmostree-postprocess.h \
src/rpmostree-pull-progress.c \
src/rpmostree-pull-progress.h \
src/rpmostree-util.c \
src/rpmostree-util.h \
src/hif-utils.c \
@ -43,6 +45,7 @@ rpm_ostree_SOURCES = src/main.c \
src/rpmostree-builtin-compose.c \
src/rpmostree-builtin-upgrade.c \
src/rpmostree-builtin-rollback.c \
src/rpmostree-builtin-rebase.c \
src/rpmostree-compose-builtin-tree.c \
src/rpmostree-compose-builtin-sign.c \
$(NULL)

View File

@ -113,6 +113,17 @@ Boston, MA 02111-1307, USA.
tree the default.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>rebase</command></term>
<listitem><para>Switch to a different remote, or a different
tree, while preserving local state in <literal>/var</literal>
and configuration in <literal>/etc</literal>. This is an
extension of <literal>upgrade</literal> which switches to a
newer version of the current current tree.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><command>compose</command></term>

View File

@ -34,6 +34,7 @@
static RpmOstreeCommand commands[] = {
{ "compose", rpmostree_builtin_compose, 0 },
{ "upgrade", rpmostree_builtin_upgrade, 0 },
{ "rebase", rpmostree_builtin_rebase, 0 },
{ "rollback", rpmostree_builtin_rollback, 0 },
{ NULL }
};

View File

@ -0,0 +1,169 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
*
* 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 <string.h>
#include <glib-unix.h>
#include "rpmostree-builtins.h"
#include "rpmostree-treepkgdiff.h"
#include "rpmostree-pull-progress.h"
#include "libgsystem.h"
static GOptionEntry option_entries[] = {
{ NULL }
};
gboolean
rpmostree_builtin_rebase (int argc,
char **argv,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GOptionContext *context = g_option_context_new ("- Switch to a different tree");
const char *new_provided_refspec;
gs_unref_object OstreeSysroot *sysroot = NULL;
gs_unref_object OstreeRepo *repo = NULL;
gs_free char *origin_refspec = NULL;
gs_free char *origin_remote = NULL;
gs_free char *origin_ref = NULL;
gs_free char *new_remote = NULL;
gs_free char *new_ref = NULL;
gs_free char *new_refspec = NULL;
gs_free char *new_revision = NULL;
gs_unref_object GFile *deployment_path = NULL;
gs_unref_object GFile *deployment_origin_path = NULL;
gs_unref_object OstreeDeployment *merge_deployment = NULL;
gs_unref_object OstreeDeployment *new_deployment = NULL;
gs_unref_object OstreeSysrootUpgrader *upgrader = NULL;
gs_unref_object OstreeAsyncProgress *progress = NULL;
gboolean changed;
GSConsole *console = NULL;
gboolean in_status_line = FALSE;
GKeyFile *old_origin;
GKeyFile *new_origin = NULL;
g_option_context_add_main_entries (context, option_entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, error))
goto out;
if (argc < 2)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"REF must be specified");
goto out;
}
new_provided_refspec = argv[1];
sysroot = ostree_sysroot_new_default ();
if (!ostree_sysroot_load (sysroot, cancellable, error))
goto out;
upgrader = ostree_sysroot_upgrader_new_for_os (sysroot, NULL,
cancellable, error);
if (!upgrader)
goto out;
old_origin = ostree_sysroot_upgrader_get_origin (upgrader);
origin_refspec = g_key_file_get_string (old_origin, "origin", "refspec", NULL);
if (!ostree_parse_refspec (origin_refspec, &origin_remote, &origin_ref, error))
goto out;
/* Allow just switching remotes */
if (g_str_has_suffix (new_provided_refspec, ":"))
{
new_remote = g_strdup (new_provided_refspec);
new_remote[strlen(new_remote)-1] = '\0';
new_ref = g_strdup (origin_ref);
}
else
{
if (!ostree_parse_refspec (new_provided_refspec, &new_remote, &new_ref, error))
goto out;
}
if (!new_remote)
new_refspec = g_strconcat (origin_remote, ":", new_ref, NULL);
else
new_refspec = g_strconcat (new_remote, ":", new_ref, NULL);
if (strcmp (origin_refspec, new_refspec) == 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Old and new refs are equal: %s", new_refspec);
goto out;
}
new_origin = ostree_sysroot_origin_new_from_refspec (sysroot, new_refspec);
if (!ostree_sysroot_upgrader_set_origin (upgrader, new_origin, cancellable, error))
goto out;
console = gs_console_get ();
if (console)
{
gs_console_begin_status_line (console, "", NULL, NULL);
progress = ostree_async_progress_new_and_connect (_rpmostree_pull_progress, console);
}
if (in_status_line)
{
gs_console_end_status_line (console, NULL, NULL);
in_status_line = FALSE;
}
/* Always allow older...there's not going to be a chronological
* relationship necessarily.
*/
if (!ostree_sysroot_upgrader_pull (upgrader, 0,
OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
progress, &changed,
cancellable, error))
goto out;
if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
goto out;
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
goto out;
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
goto out;
g_print ("Deleting ref '%s:%s'\n", origin_remote, origin_ref);
ostree_repo_transaction_set_ref (repo, origin_remote, origin_ref, NULL);
if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
goto out;
#ifdef HAVE_PATCHED_HAWKEY_AND_LIBSOLV
if (!rpmostree_print_treepkg_diff (sysroot, cancellable, error))
goto out;
#endif
ret = TRUE;
out:
return ret;
}

View File

@ -25,6 +25,7 @@
#include "rpmostree-builtins.h"
#include "rpmostree-treepkgdiff.h"
#include "rpmostree-pull-progress.h"
#include "libgsystem.h"
@ -37,56 +38,6 @@ static GOptionEntry option_entries[] = {
{ NULL }
};
static void
pull_progress (OstreeAsyncProgress *progress,
gpointer user_data)
{
GSConsole *console = user_data;
GString *buf;
gs_free char *status = NULL;
guint outstanding_fetches;
guint outstanding_writes;
guint n_scanned_metadata;
if (!console)
return;
buf = g_string_new ("");
status = ostree_async_progress_get_status (progress);
outstanding_fetches = ostree_async_progress_get_uint (progress, "outstanding-fetches");
outstanding_writes = ostree_async_progress_get_uint (progress, "outstanding-writes");
n_scanned_metadata = ostree_async_progress_get_uint (progress, "scanned-metadata");
if (status)
{
g_string_append (buf, status);
}
else if (outstanding_fetches)
{
guint64 bytes_transferred = ostree_async_progress_get_uint64 (progress, "bytes-transferred");
guint fetched = ostree_async_progress_get_uint (progress, "fetched");
guint requested = ostree_async_progress_get_uint (progress, "requested");
gs_free char *formatted_bytes_transferred =
g_format_size_full (bytes_transferred, 0);
g_string_append_printf (buf, "Receiving objects: %u%% (%u/%u) %s",
(guint)((((double)fetched) / requested) * 100),
fetched, requested, formatted_bytes_transferred);
}
else if (outstanding_writes)
{
g_string_append_printf (buf, "Writing objects: %u", outstanding_writes);
}
else
{
g_string_append_printf (buf, "Scanning metadata: %u", n_scanned_metadata);
}
gs_console_begin_status_line (console, buf->str, NULL, NULL);
g_string_free (buf, TRUE);
}
gboolean
rpmostree_builtin_upgrade (int argc,
char **argv,
@ -124,7 +75,7 @@ rpmostree_builtin_upgrade (int argc,
if (console)
{
gs_console_begin_status_line (console, "", NULL, NULL);
progress = ostree_async_progress_new_and_connect (pull_progress, console);
progress = ostree_async_progress_new_and_connect (_rpmostree_pull_progress, console);
}
if (opt_allow_downgrade)

View File

@ -34,6 +34,7 @@ typedef struct {
BUILTINPROTO(compose);
BUILTINPROTO(upgrade);
BUILTINPROTO(rebase);
BUILTINPROTO(rollback);
#undef BUILTINPROTO

View File

@ -0,0 +1,75 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
*
* 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-pull-progress.h"
#include "libgsystem.h"
void
_rpmostree_pull_progress (OstreeAsyncProgress *progress,
gpointer user_data)
{
GSConsole *console = user_data;
GString *buf;
gs_free char *status = NULL;
guint outstanding_fetches;
guint outstanding_writes;
guint n_scanned_metadata;
if (!console)
return;
buf = g_string_new ("");
status = ostree_async_progress_get_status (progress);
outstanding_fetches = ostree_async_progress_get_uint (progress, "outstanding-fetches");
outstanding_writes = ostree_async_progress_get_uint (progress, "outstanding-writes");
n_scanned_metadata = ostree_async_progress_get_uint (progress, "scanned-metadata");
if (status)
{
g_string_append (buf, status);
}
else if (outstanding_fetches)
{
guint64 bytes_transferred = ostree_async_progress_get_uint64 (progress, "bytes-transferred");
guint fetched = ostree_async_progress_get_uint (progress, "fetched");
guint requested = ostree_async_progress_get_uint (progress, "requested");
gs_free char *formatted_bytes_transferred =
g_format_size_full (bytes_transferred, 0);
g_string_append_printf (buf, "Receiving objects: %u%% (%u/%u) %s",
(guint)((((double)fetched) / requested) * 100),
fetched, requested, formatted_bytes_transferred);
}
else if (outstanding_writes)
{
g_string_append_printf (buf, "Writing objects: %u", outstanding_writes);
}
else
{
g_string_append_printf (buf, "Scanning metadata: %u", n_scanned_metadata);
}
gs_console_begin_status_line (console, buf->str, NULL, NULL);
g_string_free (buf, TRUE);
}

View File

@ -0,0 +1,27 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
*
* 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>
void
_rpmostree_pull_progress (OstreeAsyncProgress *progress,
gpointer user_data);