sysroot: Add concept of deployment "pinning" 📌

Example user story: Jane rebases her OS to a new major version N, and wants to
keep around N-1 even after a few upgrades for a while so she can easily roll
back. I plan to add `rpm-ostree rebase --pin` to opt-in to this for example.

Builds on the new `libostree-transient` group to store pinning state there.

Closes: https://github.com/ostreedev/ostree/issues/1460

Closes: #1464
Approved by: jlebon
This commit is contained in:
Colin Walters authored and Atomic Bot committed 2018-02-26 19:06:59 +00:00
1 parent c40a47e965
commit 7f88fddcd4
15 files changed
+323 -1

No files matched your search

+44
View File
@@ -1572,12 +1572,14 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot,
/* Retain deployment if:
* - we're explicitly asked to, or
* - it's pinned
* - the deployment is for another osname, or
* - we're keeping pending deployments and this is a pending deployment, or
* - this is the merge or boot deployment, or
* - we're keeping rollback deployments and this is a rollback deployment
*/
if (retain
|| ostree_deployment_is_pinned (deployment)
|| !osname_matches
|| (retain_pending && !passed_crossover)
|| (is_booted || is_merge)
@@ -1832,3 +1834,45 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
return TRUE;
}
/**
* ostree_sysroot_deployment_set_pinned:
* @self: Sysroot
* @deployment: A deployment
* @is_pinned: Whether or not deployment will be automatically GC'd
* @error: Error
*
* By default, deployments may be subject to garbage collection. Typical uses of
* libostree only retain at most 2 deployments. If @is_pinned is `TRUE`, a
* metadata bit will be set causing libostree to avoid automatic GC of the
* deployment. However, this is really an "advisory" note; it's still possible
* for e.g. older versions of libostree unaware of pinning to GC the deployment.
*
* This function does nothing and returns successfully if the deployment
* is already in the desired pinning state.
*
* Since: 2018.3
*/
gboolean
ostree_sysroot_deployment_set_pinned (OstreeSysroot *self,
OstreeDeployment *deployment,
gboolean is_pinned,
GError **error)
{
const gboolean current_pin = ostree_deployment_is_pinned (deployment);
if (is_pinned == current_pin)
return TRUE;
g_autoptr(OstreeDeployment) deployment_clone = ostree_deployment_clone (deployment);
GKeyFile *origin_clone = ostree_deployment_get_origin (deployment_clone);
if (is_pinned)
g_key_file_set_boolean (origin_clone, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", TRUE);
else
g_key_file_remove_key (origin_clone, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", NULL);
if (!ostree_sysroot_write_origin_file (self, deployment, origin_clone, NULL, error))
return FALSE;
return TRUE;
}