diff --git a/src/app/rpmostree-builtin-status.c b/src/app/rpmostree-builtin-status.c index fb959728..b9d4cd36 100644 --- a/src/app/rpmostree-builtin-status.c +++ b/src/app/rpmostree-builtin-status.c @@ -480,6 +480,7 @@ print_one_deployment (RPMOSTreeSysroot *sysroot_proxy, g_autofree char *canonrefspec = rpmostree_refspec_to_string (refspectype, refspec_data); switch (refspectype) { + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: case RPMOSTREE_REFSPEC_TYPE_OSTREE: { g_print ("%s", canonrefspec); diff --git a/src/daemon/rpmostree-sysroot-upgrader.c b/src/daemon/rpmostree-sysroot-upgrader.c index d296a7bd..ecaa37d8 100644 --- a/src/daemon/rpmostree-sysroot-upgrader.c +++ b/src/daemon/rpmostree-sysroot-upgrader.c @@ -397,6 +397,7 @@ rpmostree_sysroot_upgrader_pull_base (RpmOstreeSysrootUpgrader *self, switch (refspec_type) { + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: case RPMOSTREE_REFSPEC_TYPE_OSTREE: { g_autofree char *origin_remote = NULL; diff --git a/src/daemon/rpmostreed-deployment-utils.c b/src/daemon/rpmostreed-deployment-utils.c index 78bd6826..1648cbfb 100644 --- a/src/daemon/rpmostreed-deployment-utils.c +++ b/src/daemon/rpmostreed-deployment-utils.c @@ -303,6 +303,9 @@ rpmostreed_deployment_generate_variant (OstreeSysroot *sysroot, switch (refspec_type) { + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: + /* Nothing to do here */ + break; case RPMOSTREE_REFSPEC_TYPE_OSTREE: { if (!variant_add_remote_status (repo, refspec, base_checksum, &dict, error)) @@ -424,7 +427,9 @@ add_all_commit_details_to_vardict (OstreeDeployment *deployment, return FALSE; refspec = refspec_remainder; } - refspec_is_ostree = (refspec_type == RPMOSTREE_REFSPEC_TYPE_OSTREE); + refspec_is_ostree = refspec_type == RPMOSTREE_REFSPEC_TYPE_OSTREE; + if (refspec_type == RPMOSTREE_REFSPEC_TYPE_CHECKSUM && !commit) + checksum = refspec; g_assert (refspec); @@ -962,10 +967,14 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, return FALSE; /* we don't support rojig-based origins yet */ - if (refspectype != RPMOSTREE_REFSPEC_TYPE_OSTREE) + switch (refspectype) { + case RPMOSTREE_REFSPEC_TYPE_ROJIG: *out_update = NULL; return TRUE; /* NB: early return */ + case RPMOSTREE_REFSPEC_TYPE_OSTREE: + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: + break; } /* just skip over "ostree://" so we can talk with libostree without thinking about it */ diff --git a/src/daemon/rpmostreed-transaction-types.c b/src/daemon/rpmostreed-transaction-types.c index ddc944d5..d3d503e0 100644 --- a/src/daemon/rpmostreed-transaction-types.c +++ b/src/daemon/rpmostreed-transaction-types.c @@ -76,6 +76,7 @@ change_origin_refspec (OstreeSysroot *sysroot, return TRUE; } case RPMOSTREE_REFSPEC_TYPE_OSTREE: + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: break; } @@ -137,6 +138,9 @@ apply_revision_override (RpmostreedTransaction *transaction, RpmOstreeRefspecType refspectype; rpmostree_origin_classify_refspec (origin, &refspectype, NULL); + if (refspectype == RPMOSTREE_REFSPEC_TYPE_CHECKSUM) + return glnx_throw (error, "Cannot look up version while pinned to commit"); + g_autofree char *checksum = NULL; g_autofree char *version = NULL; if (!rpmostreed_parse_revision (revision, &checksum, &version, error)) @@ -163,6 +167,8 @@ apply_revision_override (RpmostreedTransaction *transaction, /* This case we'll look up later */ rpmostree_origin_set_rojig_version (origin, version); break; + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: + g_assert_not_reached (); /* Handled above */ } } else @@ -182,6 +188,8 @@ apply_revision_override (RpmostreedTransaction *transaction, * on. */ break; + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: + g_assert_not_reached (); /* Handled above */ } rpmostree_origin_set_override_commit (origin, checksum, version); @@ -1135,6 +1143,10 @@ deploy_transaction_execute (RpmostreedTransaction *transaction, changed = TRUE; } + /* Past this point we've computed the origin */ + RpmOstreeRefspecType refspec_type; + rpmostree_origin_classify_refspec (origin, &refspec_type, NULL); + if (download_metadata_only) { /* We have to short-circuit the usual path here; we already downloaded the ostree @@ -1246,7 +1258,10 @@ deploy_transaction_execute (RpmostreedTransaction *transaction, } else { - if (!self->revision) + if (refspec_type == RPMOSTREE_REFSPEC_TYPE_CHECKSUM + && layering_type < RPMOSTREE_SYSROOT_UPGRADER_LAYERING_RPMMD_REPOS) + rpmostree_output_message ("Pinned to commit; no upgrade available"); + else if (!self->revision) rpmostree_output_message ("No upgrade available."); else rpmostree_output_message ("No change."); diff --git a/src/libpriv/rpmostree-core.c b/src/libpriv/rpmostree-core.c index fb715d66..68ac8871 100644 --- a/src/libpriv/rpmostree-core.c +++ b/src/libpriv/rpmostree-core.c @@ -50,7 +50,9 @@ static OstreeRepo * get_pkgcache_repo (RpmOstreeContext *self); /* Given a string, look for ostree:// or rojig:// prefix and - * return its type and the remainder of the string. + * return its type and the remainder of the string. Note + * that ostree:// can be either a refspec (TYPE_OSTREE) or + * a bare commit (TYPE_COMMIT). */ gboolean rpmostree_refspec_classify (const char *refspec, @@ -58,29 +60,28 @@ rpmostree_refspec_classify (const char *refspec, const char **out_remainder, GError **error) { - if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_OSTREE_PREFIX)) - { - *out_type = RPMOSTREE_REFSPEC_TYPE_OSTREE; - if (out_remainder) - *out_remainder = refspec + strlen (RPMOSTREE_REFSPEC_OSTREE_PREFIX); - return TRUE; - } - else if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_ROJIG_PREFIX)) + if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_ROJIG_PREFIX)) { *out_type = RPMOSTREE_REFSPEC_TYPE_ROJIG; if (out_remainder) *out_remainder = refspec + strlen (RPMOSTREE_REFSPEC_ROJIG_PREFIX); return TRUE; } + /* Add any other prefixes here */ - /* Fallback case when we have no explicit prefix - treat this as ostree:// - * for compatibility. In the future we may do some error checking here, - * i.e. trying to parse the refspec. - */ - *out_type = RPMOSTREE_REFSPEC_TYPE_OSTREE; + /* For compatibility, fall back to ostree:// when we have no prefix. */ + const char *remainder; + if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_OSTREE_PREFIX)) + remainder = refspec + strlen (RPMOSTREE_REFSPEC_OSTREE_PREFIX); + else + remainder = refspec; + + if (ostree_validate_checksum_string (remainder, NULL)) + *out_type = RPMOSTREE_REFSPEC_TYPE_CHECKSUM; + else + *out_type = RPMOSTREE_REFSPEC_TYPE_OSTREE; if (out_remainder) - *out_remainder = refspec; - + *out_remainder = remainder; return TRUE; } @@ -92,6 +93,7 @@ rpmostree_refspec_to_string (RpmOstreeRefspecType reftype, switch (reftype) { case RPMOSTREE_REFSPEC_TYPE_OSTREE: + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: prefix = RPMOSTREE_REFSPEC_OSTREE_PREFIX; break; case RPMOSTREE_REFSPEC_TYPE_ROJIG: diff --git a/src/libpriv/rpmostree-core.h b/src/libpriv/rpmostree-core.h index 83e880d5..63bf5db7 100644 --- a/src/libpriv/rpmostree-core.h +++ b/src/libpriv/rpmostree-core.h @@ -51,6 +51,7 @@ G_DECLARE_FINAL_TYPE (RpmOstreeTreespec, rpmostree_treespec, RPMOSTREE, TREESPEC typedef enum { RPMOSTREE_REFSPEC_TYPE_OSTREE, RPMOSTREE_REFSPEC_TYPE_ROJIG, + RPMOSTREE_REFSPEC_TYPE_CHECKSUM, } RpmOstreeRefspecType; #define RPMOSTREE_REFSPEC_OSTREE_PREFIX "ostree://" diff --git a/src/libpriv/rpmostree-origin.c b/src/libpriv/rpmostree-origin.c index 6c8a5005..c2b1a144 100644 --- a/src/libpriv/rpmostree-origin.c +++ b/src/libpriv/rpmostree-origin.c @@ -125,7 +125,8 @@ rpmostree_origin_parse_keyfile (GKeyFile *origin, return glnx_null_throw (error, "Duplicate origin/refspec and origin/rojig in deployment origin"); else if (refspec) { - ret->refspec_type = RPMOSTREE_REFSPEC_TYPE_OSTREE; + if (!rpmostree_refspec_classify (refspec, &ret->refspec_type, NULL, error)) + return FALSE; /* Note the lack of a prefix here so that code that just calls * rpmostree_origin_get_refspec() in the ostree:// case * sees it without the prefix for compatibility. @@ -206,6 +207,7 @@ rpmostree_origin_get_full_refspec (RpmOstreeOrigin *origin, switch (origin->refspec_type) { case RPMOSTREE_REFSPEC_TYPE_OSTREE: + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: return g_strdup (origin->cached_refspec); case RPMOSTREE_REFSPEC_TYPE_ROJIG: return g_strconcat (RPMOSTREE_REFSPEC_ROJIG_PREFIX, origin->cached_refspec, NULL); @@ -485,6 +487,7 @@ rpmostree_origin_set_rebase (RpmOstreeOrigin *origin, origin->cached_refspec = g_strdup (refspecdata); switch (origin->refspec_type) { + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: case RPMOSTREE_REFSPEC_TYPE_OSTREE: { g_key_file_remove_key (origin->kf, "origin", "rojig", NULL); @@ -577,6 +580,7 @@ update_keyfile_pkgs_from_cache (RpmOstreeOrigin *origin, switch (origin->refspec_type) { case RPMOSTREE_REFSPEC_TYPE_OSTREE: + case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: { g_key_file_set_value (origin->kf, "origin", "baserefspec", origin->cached_refspec); diff --git a/tests/vmcheck/test-pinned-commit.sh b/tests/vmcheck/test-pinned-commit.sh new file mode 100755 index 00000000..f0f74d76 --- /dev/null +++ b/tests/vmcheck/test-pinned-commit.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This library 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 License, 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. + +set -euo pipefail + +. ${commondir}/libtest.sh +. ${commondir}/libvm.sh + +set -x + +checksum=$(vm_get_booted_csum) +vm_rpmostree rebase :${checksum} +vm_assert_status_jq ".deployments[0][\"origin\"] == \"${checksum}\"" +vm_rpmostree status > status.txt +assert_file_has_content status.txt '^ ostree://'${checksum} +echo "ok pin to commit" + +vm_rpmostree upgrade >out.txt +assert_file_has_content out.txt 'Pinned to commit; no upgrade available' +if vm_rpmostree deploy 42 2>err.txt; then + fatal "deployed version from commit?" +fi +assert_file_has_content err.txt 'Cannot look up version while pinned to commit' +echo "ok cmds"