diff --git a/man/ostree-admin-pin.xml b/man/ostree-admin-pin.xml
index ba3aa4a0c9..78edde4705 100644
--- a/man/ostree-admin-pin.xml
+++ b/man/ostree-admin-pin.xml
@@ -58,8 +58,10 @@ License along with this library. If not, see .
Ensures the deployment at INDEX, will not be garbage
- collected by default. This is termed "pinning". If the
+ collected by default. This is termed "pinning". If the
-u option is provided, undoes a pinning operation.
+ INDEX can be >= 0 or one of booted, pending or
+ rollback strings.
diff --git a/src/ostree/ot-admin-builtin-pin.c b/src/ostree/ot-admin-builtin-pin.c
index de219d7e43..2ed8fbb756 100644
--- a/src/ostree/ot-admin-builtin-pin.c
+++ b/src/ostree/ot-admin-builtin-pin.c
@@ -31,6 +31,53 @@ static gboolean opt_unpin;
static GOptionEntry options[]
= { { "unpin", 'u', 0, G_OPTION_ARG_NONE, &opt_unpin, "Unset pin", NULL }, { NULL } };
+static gint64
+get_deployment_index_for_type (OstreeSysroot *sysroot, const char *deploy_index_str)
+{
+ g_autoptr (GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
+ OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
+ if (booted_deployment && deploy_index_str[0] == 'b')
+ return ostree_deployment_get_index (booted_deployment);
+
+ g_autoptr (OstreeDeployment) pending_deployment = NULL;
+ g_autoptr (OstreeDeployment) rollback_deployment = NULL;
+ if (booted_deployment)
+ ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment, &rollback_deployment);
+
+ if (pending_deployment && deploy_index_str[0] == 'p')
+ return ostree_deployment_get_index (pending_deployment);
+ else if (rollback_deployment && deploy_index_str[0] == 'r')
+ return ostree_deployment_get_index (rollback_deployment);
+
+ return -1;
+}
+
+static gboolean
+do_pinning (OstreeSysroot *sysroot, const gint64 deploy_index, GError **error)
+{
+ g_autoptr (OstreeDeployment) target_deployment
+ = ot_admin_get_indexed_deployment (sysroot, deploy_index, error);
+ if (!target_deployment)
+ return FALSE;
+
+ const gboolean current_pin = ostree_deployment_is_pinned (target_deployment);
+ const gboolean desired_pin = !opt_unpin;
+ if (current_pin == desired_pin)
+ {
+ g_print ("Deployment %lld is already %s\n", (long long int)deploy_index,
+ current_pin ? "pinned" : "unpinned");
+ return TRUE;
+ }
+ else if (ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, error))
+ {
+ g_print ("Deployment %lld is now %s\n", (long long int)deploy_index,
+ desired_pin ? "pinned" : "unpinned");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
gboolean
ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation,
GCancellable *cancellable, GError **error)
@@ -54,32 +101,25 @@ ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation
char *endptr = NULL;
errno = 0;
- const guint64 deploy_index = g_ascii_strtoull (deploy_index_str, &endptr, 10);
- if (*endptr != '\0')
- return glnx_throw (error, "Invalid index: %s", deploy_index_str);
- if (errno == ERANGE)
- return glnx_throw (error, "Index too large: %s", deploy_index_str);
-
- g_autoptr (OstreeDeployment) target_deployment
- = ot_admin_get_indexed_deployment (sysroot, deploy_index, error);
- if (!target_deployment)
- return FALSE;
-
- gboolean current_pin = ostree_deployment_is_pinned (target_deployment);
- const gboolean desired_pin = !opt_unpin;
- if (current_pin == desired_pin)
+ gint64 deploy_index;
+ if (!g_strcmp0 (deploy_index_str, "booted") || !g_strcmp0 (deploy_index_str, "pending")
+ || !g_strcmp0 (deploy_index_str, "rollback"))
{
- g_print ("Deployment %s is already %s\n", deploy_index_str,
- current_pin ? "pinned" : "unpinned");
+ deploy_index = get_deployment_index_for_type (sysroot, deploy_index_str);
+ if (deploy_index < 0)
+ return glnx_throw (error, "Deployment type not found: %s", deploy_index_str);
}
else
{
- if (!ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin,
- error))
- return FALSE;
- g_print ("Deployment %s is now %s\n", deploy_index_str,
- desired_pin ? "pinned" : "unpinned");
+ deploy_index = g_ascii_strtoull (deploy_index_str, &endptr, 10);
+ if (*endptr != '\0')
+ return glnx_throw (error, "Invalid index: %s", deploy_index_str);
+ else if (errno == ERANGE)
+ return glnx_throw (error, "Index too large: %s", deploy_index_str);
}
+
+ if (!do_pinning (sysroot, deploy_index, error))
+ return FALSE;
}
return TRUE;
diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c
index 68a54751f0..53face6a2d 100644
--- a/src/ostree/ot-builtin-admin.c
+++ b/src/ostree/ot-builtin-admin.c
@@ -53,7 +53,8 @@ static OstreeCommand admin_subcommands[] = {
{ "stateroot-init", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_os_init,
"Initialize empty state for given operating system" },
{ "pin", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_pin,
- "Change the \"pinning\" state of a deployment" },
+ "Change the \"pinning\" state of a deployment, INDEX can be >= 0 or one of booted, pending or "
+ "rollback strings" },
{ "post-copy", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_post_copy,
"Update the repo and deployments as needed after a copy" },
{ "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_set_origin,