compose: Introduce variable substitution for ${basearch}

This comes from the tradition of yum repo files.  It's significantly
easier for rpm-ostree users building multiple architectures if some
core templating for the treefiles is built in.

Otherwise, everyone needs to learn about a new wrapper tool for
rpm-ostree, and said tool would need to re-do the same "basearch"
evaluation that is already occuring inside libhif.

This commit also paves the way for introducing `${releasever}`
substitution.

NOTE: This depends on pending changes to libhif git.

Closes: #274
Approved by: jlebon
This commit is contained in:
Colin Walters 2016-04-28 08:59:20 -04:00 committed by Colin Walters (automation)
parent e2e754e94c
commit 4fc25d74a3
7 changed files with 106 additions and 11 deletions

View File

@ -213,6 +213,7 @@ set_keyfile_string_array_from_json (GKeyFile *keyfile,
static gboolean
install_packages_in_root (RpmOstreeTreeComposeContext *self,
RpmOstreeContext *ctx,
JsonObject *treedata,
GFile *yumroot,
char **packages,
@ -225,7 +226,6 @@ install_packages_in_root (RpmOstreeTreeComposeContext *self,
guint progress_sigid;
GFile *contextdir = self->treefile_context_dirs->pdata[0];
g_autoptr(RpmOstreeInstall) hifinstall = { 0, };
g_autoptr(RpmOstreeContext) ctx = NULL;
HifContext *hifctx;
gs_free char *ret_new_inputhash = NULL;
g_autoptr(GKeyFile) treespec = g_key_file_new ();
@ -245,9 +245,6 @@ install_packages_in_root (RpmOstreeTreeComposeContext *self,
}
#endif
ctx = rpmostree_context_new_unprivileged (self->cachedir_dfd, cancellable, error);
if (!ctx)
goto out;
hifctx = rpmostree_context_get_hif (ctx);
if (opt_proxy)
hif_context_set_http_proxy (hifctx, opt_proxy);
@ -577,6 +574,8 @@ rpmostree_compose_builtin_tree (int argc,
gs_unref_object JsonParser *treefile_parser = NULL;
gs_unref_variant_builder GVariantBuilder *metadata_builder =
g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_autoptr(RpmOstreeContext) corectx = NULL;
g_autoptr(GHashTable) varsubsts = NULL;
gboolean workdir_is_tmp = FALSE;
self->treefile_context_dirs = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
@ -676,6 +675,12 @@ rpmostree_compose_builtin_tree (int argc,
goto out;
}
corectx = rpmostree_context_new_unprivileged (self->cachedir_dfd, cancellable, error);
if (!corectx)
goto out;
varsubsts = rpmostree_context_get_varsubsts (corectx);
treefile_parser = json_parser_new ();
if (!json_parser_load_from_file (treefile_parser,
gs_file_get_path_cached (treefile_path),
@ -708,9 +713,13 @@ rpmostree_compose_builtin_tree (int argc,
goto out;
}
self->ref = g_strdup (_rpmostree_jsonutil_object_require_string_member (treefile, "ref", error));
if (!self->ref)
goto out;
{ const char *input_ref = _rpmostree_jsonutil_object_require_string_member (treefile, "ref", error);
if (!input_ref)
goto out;
self->ref = _rpmostree_varsubst_string (input_ref, varsubsts, error);
if (!self->ref)
goto out;
}
if (!ostree_repo_read_commit (repo, self->ref, &previous_root, &previous_checksum,
cancellable, &temp_error))
@ -809,7 +818,7 @@ rpmostree_compose_builtin_tree (int argc,
{ gboolean unmodified = FALSE;
if (!install_packages_in_root (self, treefile, yumroot,
if (!install_packages_in_root (self, corectx, treefile, yumroot,
(char**)packages->pdata,
opt_force_nocache ? NULL : &unmodified,
&new_inputhash,

View File

@ -404,6 +404,16 @@ rpmostree_treespec_to_variant (RpmOstreeTreespec *spec)
return g_variant_ref (spec->spec);
}
GHashTable *
rpmostree_context_get_varsubsts (RpmOstreeContext *context)
{
GHashTable *r = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
g_hash_table_insert (r, g_strdup ("basearch"), g_strdup (hif_context_get_base_arch (context->hifctx)));
return r;
}
static gboolean
enable_one_repo (RpmOstreeContext *context,
GPtrArray *sources,

View File

@ -50,6 +50,8 @@ RpmOstreeTreespec *rpmostree_treespec_new_from_keyfile (GKeyFile *keyfile, GErro
RpmOstreeTreespec *rpmostree_treespec_new_from_path (const char *path, GError **error);
RpmOstreeTreespec *rpmostree_treespec_new (GVariant *variant);
GHashTable *rpmostree_context_get_varsubsts (RpmOstreeContext *context);
GVariant *rpmostree_treespec_to_variant (RpmOstreeTreespec *spec);
const char *rpmostree_treespec_get_ref (RpmOstreeTreespec *spec);

View File

@ -121,6 +121,70 @@ rpmostree_mkdtemp (const char *template,
return ret;
}
/* Given a string of the form
* "bla blah ${foo} blah ${bar}"
* and a hash table of variables, substitute the variable values.
*/
char *
_rpmostree_varsubst_string (const char *instr,
GHashTable *substitutions,
GError **error)
{
const char *s;
const char *p;
/* Acts as a reusable buffer space */
g_autoptr(GString) varnamebuf = g_string_new ("");
g_autoptr(GString) result = g_string_new ("");
s = instr;
while ((p = strstr (s, "${")) != NULL)
{
const char *varstart = p + 2;
const char *varend = strchr (varstart, '}');
const char *value;
if (!varend)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unclosed variable reference starting at %u bytes",
(guint)(p - instr));
return NULL;
}
/* Append leading bytes */
g_string_append_len (result, s, p - s);
/* Get a NUL-terminated copy of the variable name */
g_string_truncate (varnamebuf, 0);
g_string_append_len (varnamebuf, varstart, varend - varstart);
value = g_hash_table_lookup (substitutions, varnamebuf->str);
if (!value)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unknown variable reference ${%s}",
varnamebuf->str);
return NULL;
}
/* Append the replaced value */
g_string_append (result, value);
/* On to the next */
s = varend+1;
}
if (s != instr)
{
char *r;
g_string_append_len (result, s, p - s);
/* Steal the C string, NULL out the GString since we freed it */
r = g_string_free (result, FALSE);
result = NULL;
return r;
}
else
return g_strdup (instr);
}
gboolean
_rpmostree_util_enumerate_directory_allow_noent (GFile *dirpath,
const char *queryargs,

View File

@ -47,6 +47,11 @@ gboolean rpmostree_mkdtemp (const char *template,
int *out_tmpdir_dfd, /* allow-none */
GError **error);
char *
_rpmostree_varsubst_string (const char *instr,
GHashTable *substitutions,
GError **error);
gboolean
_rpmostree_util_enumerate_directory_allow_noent (GFile *dirpath,
const char *queryargs,

View File

@ -1,5 +1,5 @@
{
"ref": "fedora/test",
"ref": "fedora/${basearch}/test",
"repos": ["test-repo"],

View File

@ -27,7 +27,12 @@ check_root_test
# Remove once it doesn't happen anymore.
unset G_DEBUG
(arch | grep -q x86_64) || { echo 1>&2 "$0 can be run only on x86_64"; echo "1..0" ; exit 77; }
arch=$(arch)
if ! test "${arch}" = x86_64; then
echo 1>&2 "$0 can be run only on x86_64"; echo "1..0" ; exit 77
fi
testref=fedora/${arch}/test
echo "1..4"
@ -44,7 +49,7 @@ echo "ok dry run"
rpm-ostree --repo=repo compose tree $SRCDIR/test-repo.json
ostree --repo=repo refs >refs.txt
assert_file_has_content refs.txt fedora/test
assert_file_has_content refs.txt ${testref}
echo "ok compose"