rebase: add support for rebasing to a specific rev
Expand the available options in the Rebase() D-Bus method to also have a "revision" key. Its value has the same semantics as the "revision" key in the Deploy() method (e.g. the "revision=" and "version=" prefixes are also supported). Also expand the rebase CLI to allow for specifying the revision as an additional argument. This allows users to rebase to a specific version or checksum, rather than only to the latest. Conceptually, this is the equivalent of doing a rebase followed by a deploy. I.e. we specify an override-commit in the origin and expect the same behaviours that apply after a deploy to also apply here. Closes: #212 Closes: #555 Approved by: cgwalters
This commit is contained in:
parent
c5fa202378
commit
e10c97007f
@ -42,7 +42,7 @@ static GOptionEntry option_entries[] = {
|
||||
};
|
||||
|
||||
static GVariant *
|
||||
get_args_variant (void)
|
||||
get_args_variant (const char *revision)
|
||||
{
|
||||
GVariantDict dict;
|
||||
|
||||
@ -50,6 +50,9 @@ get_args_variant (void)
|
||||
g_variant_dict_insert (&dict, "skip-purge", "b", opt_skip_purge);
|
||||
g_variant_dict_insert (&dict, "reboot", "b", opt_reboot);
|
||||
|
||||
if (revision != NULL)
|
||||
g_variant_dict_insert (&dict, "revision", "s", revision);
|
||||
|
||||
return g_variant_dict_end (&dict);
|
||||
}
|
||||
|
||||
@ -61,11 +64,12 @@ rpmostree_builtin_rebase (int argc,
|
||||
{
|
||||
int exit_status = EXIT_FAILURE;
|
||||
const char *new_provided_refspec;
|
||||
const char *revision = NULL;
|
||||
|
||||
/* forced blank for now */
|
||||
const char *packages[] = { NULL };
|
||||
|
||||
g_autoptr(GOptionContext) context = g_option_context_new ("REFSPEC - Switch to a different tree");
|
||||
g_autoptr(GOptionContext) context = g_option_context_new ("REFSPEC [REVISION] - Switch to a different tree");
|
||||
glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
|
||||
glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
|
||||
g_autofree char *transaction_address = NULL;
|
||||
@ -79,20 +83,23 @@ rpmostree_builtin_rebase (int argc,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (argc < 2)
|
||||
if (argc < 2 || argc > 3)
|
||||
{
|
||||
rpmostree_usage_error (context, "REFSPEC must be specified", error);
|
||||
rpmostree_usage_error (context, "Too few or too many arguments", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_provided_refspec = argv[1];
|
||||
|
||||
if (argc == 3)
|
||||
revision = argv[2];
|
||||
|
||||
if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname,
|
||||
cancellable, &os_proxy, error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_os_call_rebase_sync (os_proxy,
|
||||
get_args_variant (),
|
||||
get_args_variant (revision),
|
||||
new_provided_refspec,
|
||||
packages,
|
||||
&transaction_address,
|
||||
|
@ -144,6 +144,7 @@
|
||||
<!-- Available options:
|
||||
"skip-purge" (type 'b')
|
||||
"reboot" (type 'b')
|
||||
"revision" (type 's')
|
||||
-->
|
||||
<method name="Rebase">
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
|
@ -649,6 +649,7 @@ os_handle_rebase (RPMOSTreeOS *interface,
|
||||
GVariantDict options_dict;
|
||||
gboolean opt_skip_purge = FALSE;
|
||||
const char *osname;
|
||||
const char *opt_revision = NULL;
|
||||
gboolean opt_reboot = FALSE;
|
||||
GError *local_error = NULL;
|
||||
|
||||
@ -683,6 +684,9 @@ os_handle_rebase (RPMOSTreeOS *interface,
|
||||
g_variant_dict_lookup (&options_dict,
|
||||
"reboot", "b",
|
||||
&opt_reboot);
|
||||
g_variant_dict_lookup (&options_dict,
|
||||
"revision", "&s",
|
||||
&opt_revision);
|
||||
|
||||
g_variant_dict_clear (&options_dict);
|
||||
|
||||
@ -690,6 +694,7 @@ os_handle_rebase (RPMOSTreeOS *interface,
|
||||
ot_sysroot,
|
||||
osname,
|
||||
arg_refspec,
|
||||
opt_revision,
|
||||
opt_skip_purge,
|
||||
opt_reboot,
|
||||
cancellable,
|
||||
|
@ -71,6 +71,82 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
apply_revision_override (RpmostreedTransaction *transaction,
|
||||
OstreeRepo *repo,
|
||||
OstreeAsyncProgress *progress,
|
||||
RpmOstreeSysrootUpgrader *upgrader,
|
||||
const char *revision,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GKeyFile) origin = NULL;
|
||||
g_autofree char *checksum = NULL;
|
||||
g_autofree char *version = NULL;
|
||||
const char *refspec;
|
||||
|
||||
origin = rpmostree_sysroot_upgrader_dup_origin (upgrader);
|
||||
if (origin == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Booted deployment has no origin");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!rpmostreed_parse_revision (revision,
|
||||
&checksum,
|
||||
&version,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
refspec = rpmostree_sysroot_upgrader_get_refspec (upgrader);
|
||||
if (refspec == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Could not find refspec for booted deployment");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (version != NULL)
|
||||
{
|
||||
rpmostreed_transaction_emit_message_printf (transaction,
|
||||
"Resolving version '%s'",
|
||||
version);
|
||||
|
||||
if (!rpmostreed_repo_lookup_version (repo, refspec, version, progress,
|
||||
cancellable, &checksum, error))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (checksum != NULL);
|
||||
|
||||
rpmostreed_transaction_emit_message_printf (transaction,
|
||||
"Validating checksum '%s'",
|
||||
checksum);
|
||||
|
||||
if (!rpmostreed_repo_lookup_checksum (repo, refspec, checksum,
|
||||
progress, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_key_file_set_string (origin, "origin", "override-commit", checksum);
|
||||
|
||||
if (version != NULL)
|
||||
{
|
||||
g_autofree char *comment = NULL;
|
||||
|
||||
/* Add a comment with the version, to be nice. */
|
||||
comment = g_strdup_printf ("Version %s [%.10s]", version, checksum);
|
||||
g_key_file_set_comment (origin, "origin", "override-commit", comment, NULL);
|
||||
}
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_set_origin (upgrader, origin, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ============================= Package Diff ============================= */
|
||||
|
||||
typedef struct {
|
||||
@ -682,6 +758,7 @@ typedef struct {
|
||||
RpmostreedTransaction parent;
|
||||
char *osname;
|
||||
char *refspec;
|
||||
char *revision;
|
||||
gboolean skip_purge;
|
||||
gboolean reboot;
|
||||
} RebaseTransaction;
|
||||
@ -755,6 +832,13 @@ rebase_transaction_execute (RpmostreedTransaction *transaction,
|
||||
rpmostreed_transaction_connect_download_progress (transaction, progress);
|
||||
rpmostreed_transaction_connect_signature_progress (transaction, repo);
|
||||
|
||||
if (self->revision)
|
||||
{
|
||||
if (!apply_revision_override (transaction, repo, progress, upgrader,
|
||||
self->revision, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_pull (upgrader, NULL, 0,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
@ -810,6 +894,7 @@ rpmostreed_transaction_new_rebase (GDBusMethodInvocation *invocation,
|
||||
OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
const char *refspec,
|
||||
const char *revision,
|
||||
gboolean skip_purge,
|
||||
gboolean reboot,
|
||||
GCancellable *cancellable,
|
||||
@ -832,6 +917,7 @@ rpmostreed_transaction_new_rebase (GDBusMethodInvocation *invocation,
|
||||
{
|
||||
self->osname = g_strdup (osname);
|
||||
self->refspec = g_strdup (refspec);
|
||||
self->revision = g_strdup (revision);
|
||||
self->skip_purge = skip_purge;
|
||||
self->reboot = reboot;
|
||||
}
|
||||
@ -880,11 +966,6 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
|
||||
g_autoptr(GKeyFile) origin = NULL;
|
||||
g_autofree char *checksum = NULL;
|
||||
g_autofree char *version = NULL;
|
||||
const char *refspec = NULL;
|
||||
|
||||
gboolean changed = FALSE;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
@ -903,77 +984,12 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
|
||||
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
origin = rpmostree_sysroot_upgrader_dup_origin (upgrader);
|
||||
if (origin == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Booted deployment has no origin");
|
||||
goto out;
|
||||
}
|
||||
|
||||
progress = ostree_async_progress_new ();
|
||||
rpmostreed_transaction_connect_download_progress (transaction, progress);
|
||||
rpmostreed_transaction_connect_signature_progress (transaction, repo);
|
||||
|
||||
if (!rpmostreed_parse_revision (self->revision,
|
||||
&checksum,
|
||||
&version,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
refspec = rpmostree_sysroot_upgrader_get_refspec (upgrader);
|
||||
if (refspec == NULL)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Could not find refspec for booted deployment");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (version != NULL)
|
||||
{
|
||||
|
||||
rpmostreed_transaction_emit_message_printf (transaction,
|
||||
"Resolving version '%s'",
|
||||
version);
|
||||
|
||||
if (!rpmostreed_repo_lookup_version (repo,
|
||||
refspec,
|
||||
version,
|
||||
progress,
|
||||
cancellable,
|
||||
&checksum,
|
||||
error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (checksum != NULL);
|
||||
|
||||
rpmostreed_transaction_emit_message_printf (transaction,
|
||||
"Validating checksum '%s'",
|
||||
checksum);
|
||||
|
||||
if (!rpmostreed_repo_lookup_checksum (repo,
|
||||
refspec,
|
||||
checksum,
|
||||
progress,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_key_file_set_string (origin, "origin", "override-commit", checksum);
|
||||
|
||||
if (version != NULL)
|
||||
{
|
||||
g_autofree char *comment = NULL;
|
||||
|
||||
/* Add a comment with the version, to be nice. */
|
||||
comment = g_strdup_printf ("Version %s [%.10s]", version, checksum);
|
||||
g_key_file_set_comment (origin, "origin", "override-commit", comment, NULL);
|
||||
}
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_set_origin (upgrader, origin, cancellable, error))
|
||||
if (!apply_revision_override (transaction, repo, progress, upgrader,
|
||||
self->revision, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_pull (upgrader, NULL, 0,
|
||||
|
@ -59,6 +59,7 @@ RpmostreedTransaction *
|
||||
OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
const char *refspec,
|
||||
const char *revision,
|
||||
gboolean skip_purge,
|
||||
gboolean reboot,
|
||||
GCancellable *cancellable,
|
||||
|
@ -23,7 +23,7 @@ set -e
|
||||
|
||||
ensure_dbus
|
||||
|
||||
echo "1..10"
|
||||
echo "1..13"
|
||||
|
||||
setup_os_repository "archive-z2" "syslinux"
|
||||
|
||||
@ -109,6 +109,31 @@ fi
|
||||
assert_file_has_content OUTPUT-err 'Checksum .* not found in .*'
|
||||
echo "ok error on deploying commit on other branch"
|
||||
|
||||
# Make sure we're currently on otheros
|
||||
rpm-ostree status | head --lines 5 | tee OUTPUT-status.txt
|
||||
assert_file_has_content OUTPUT-status.txt otheros:testos/buildmaster/x86_64-runtime
|
||||
|
||||
os_repository_new_commit 2 2
|
||||
rpm-ostree rebase --os=testos testos:testos/buildmaster/x86_64-runtime $(date "+%Y%m%d.2")
|
||||
rpm-ostree status | head --lines 5 | tee OUTPUT-status.txt
|
||||
assert_file_has_content OUTPUT-status.txt testos
|
||||
assert_file_has_content OUTPUT-status.txt $(date "+%Y%m%d\.2")
|
||||
echo "ok rebase onto other branch at specific version"
|
||||
|
||||
branch=testos/buildmaster/x86_64-runtime
|
||||
new_csum=$(ostree --repo=${test_tmpdir}/testos-repo commit -b $branch --tree=ref=$branch)
|
||||
rpm-ostree rebase --os=testos otheros:testos/buildmaster/x86_64-runtime $new_csum
|
||||
rpm-ostree status | head --lines 5 | tee OUTPUT-status.txt
|
||||
assert_file_has_content OUTPUT-status.txt otheros
|
||||
assert_file_has_content OUTPUT-status.txt $new_csum
|
||||
echo "ok rebase onto other branch at specific checksum"
|
||||
|
||||
if rpm-ostree rebase --os=testos testos:testos/buildmaster/x86_64-runtime $other_rev 2>OUTPUT-err; then
|
||||
assert_not_reached "Rebasing onto out-of-branch commit unexpectedly succeeded."
|
||||
fi
|
||||
assert_file_has_content OUTPUT-err 'Checksum .* not found in .*'
|
||||
echo "ok error on rebasing onto commit on other branch"
|
||||
|
||||
# Ensure it returns an error when passing a wrong option.
|
||||
rpm-ostree --help | awk '/^$/ {in_commands=0} {if(in_commands==1){print $0}} /^Builtin Commands:/ {in_commands=1}' > commands
|
||||
while read command; do
|
||||
|
@ -341,6 +341,7 @@ os_repository_new_commit ()
|
||||
echo "content iteration ${content_iteration}" > usr/bin/content-iteration
|
||||
|
||||
version=$(date "+%Y%m%d.${content_iteration}")
|
||||
echo "version: $version"
|
||||
|
||||
ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string "version=${version}" -b testos/buildmaster/x86_64-runtime -s "Build"
|
||||
cd ${test_tmpdir}
|
||||
|
Loading…
Reference in New Issue
Block a user