Skip to content

Commit f89f5cd

Browse files
committed
compose: Use GVariantDict, not manual hash table
There's a dedicated type for a mapping from "string to variant" in `GVariantDict`. Use it instead of rolling our own with `GHashTable`. The advantage here is improved ergonomics from the C side; e.g. we can directly pass C strings for values and have the variant allocated internally. But more importantly, this is prep for oxidizing things here because we can pass `GVariantDict` to/from Rust easily, not so with `GHashTable`.
1 parent d44d81d commit f89f5cd

3 files changed

+62
-55
lines changed

src/app/rpmostree-compose-builtin-tree.cxx

+30-34
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ typedef struct
155155
{
156156
RpmOstreeContext *corectx;
157157
GFile *treefile_path;
158-
GHashTable *metadata;
159-
GHashTable *detached_metadata;
158+
GVariantDict *metadata;
159+
GVariantDict *detached_metadata;
160160
gboolean failed;
161161
GLnxTmpDir workdir_tmp;
162162
int workdir_dfd;
@@ -181,7 +181,8 @@ rpm_ostree_tree_compose_context_free (RpmOstreeTreeComposeContext *ctx)
181181
{
182182
g_clear_object (&ctx->corectx);
183183
g_clear_object (&ctx->treefile_path);
184-
g_clear_pointer (&ctx->metadata, g_hash_table_unref);
184+
g_clear_pointer (&ctx->metadata, g_variant_dict_unref);
185+
g_clear_pointer (&ctx->detached_metadata, g_variant_dict_unref);
185186
ctx->treefile_rs.~optional ();
186187
/* Only close workdir_dfd if it's not owned by the tmpdir */
187188
if (!ctx->workdir_tmp.initialized)
@@ -515,17 +516,17 @@ install_packages (RpmOstreeTreeComposeContext *self, gboolean *out_unmodified,
515516
}
516517

517518
static gboolean
518-
parse_metadata_keyvalue_strings (char **strings, GHashTable *metadata_hash, GError **error)
519+
parse_metadata_keyvalue_strings (char **strings, GVariantDict *metadata_hash, GError **error)
519520
{
520521
for (char **iter = strings; *iter; iter++)
521522
{
522523
const char *s = *iter;
523524
const char *eq = strchr (s, '=');
524525
if (!eq)
525526
return glnx_throw (error, "Missing '=' in KEY=VALUE metadata '%s'", s);
527+
g_autofree char *k = g_strndup (s, eq - s);
526528

527-
g_hash_table_insert (metadata_hash, g_strndup (s, eq - s),
528-
g_variant_ref_sink (g_variant_new_string (eq + 1)));
529+
g_variant_dict_insert (metadata_hash, k, "s", eq + 1);
529530
}
530531

531532
return TRUE;
@@ -762,10 +763,8 @@ rpm_ostree_compose_context_new (const char *treefile_pathstr, const char *basear
762763

763764
self->treefile = json_node_get_object (self->treefile_rootval);
764765

765-
self->metadata
766-
= g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
767-
self->detached_metadata
768-
= g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
766+
self->metadata = g_variant_dict_new (NULL);
767+
self->detached_metadata = g_variant_dict_new (NULL);
769768

770769
/* metadata from the treefile itself has the lowest priority */
771770
JsonNode *add_commit_metadata_node
@@ -805,8 +804,8 @@ rpm_ostree_compose_context_new (const char *treefile_pathstr, const char *basear
805804
{
806805
g_variant_builder_add (&builder, "s", s.c_str ());
807806
}
808-
g_hash_table_insert (self->metadata, g_strdup ("ostree.container-cmd"),
809-
g_variant_ref_sink (g_variant_builder_end (&builder)));
807+
g_variant_dict_insert_value (self->metadata, "ostree.container-cmd",
808+
g_variant_builder_end (&builder));
810809
}
811810

812811
auto layers = (*self->treefile_rs)->get_all_ostree_layers ();
@@ -836,8 +835,7 @@ inject_advisories (RpmOstreeTreeComposeContext *self, GCancellable *cancellable,
836835
g_autoptr (GVariant) advisories = rpmostree_advisories_variant (yum_sack, pkgs);
837836

838837
if (advisories && g_variant_n_children (advisories) > 0)
839-
g_hash_table_insert (self->metadata, g_strdup ("rpmostree.advisories"),
840-
g_steal_pointer (&advisories));
838+
g_variant_dict_insert_value (self->metadata, "rpmostree.advisories", advisories);
841839

842840
return TRUE;
843841
}
@@ -918,7 +916,7 @@ impl_install_tree (RpmOstreeTreeComposeContext *self, gboolean *out_changed,
918916
rust::String next_version;
919917
if (json_object_has_member (self->treefile, "automatic-version-prefix") &&
920918
/* let --add-metadata-string=version=... take precedence */
921-
!g_hash_table_contains (self->metadata, OSTREE_COMMIT_META_KEY_VERSION))
919+
!g_variant_dict_contains (self->metadata, OSTREE_COMMIT_META_KEY_VERSION))
922920
{
923921
CXX_TRY_VAR (ver_prefix, (*self->treefile_rs)->require_automatic_version_prefix (), error);
924922
auto ver_suffix = (*self->treefile_rs)->get_automatic_version_suffix ();
@@ -941,17 +939,15 @@ impl_install_tree (RpmOstreeTreeComposeContext *self, gboolean *out_changed,
941939
last_version ?: ""),
942940
error);
943941
next_version = std::move (next_versionv);
944-
g_hash_table_insert (self->metadata, g_strdup (OSTREE_COMMIT_META_KEY_VERSION),
945-
g_variant_ref_sink (g_variant_new_string (next_version.c_str ())));
942+
g_variant_dict_insert (self->metadata, OSTREE_COMMIT_META_KEY_VERSION, "s",
943+
next_version.c_str ());
946944
}
947945
else
948946
{
949-
gpointer vp = g_hash_table_lookup (self->metadata, OSTREE_COMMIT_META_KEY_VERSION);
950-
auto v = static_cast<GVariant *> (vp);
951-
if (v)
947+
const char *version = NULL;
948+
if (g_variant_dict_lookup (self->metadata, "&s", OSTREE_COMMIT_META_KEY_VERSION, &version))
952949
{
953-
g_assert (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING));
954-
next_version = rust::String (static_cast<char *> (g_variant_dup_string (v, NULL)));
950+
next_version = rust::String (version);
955951
}
956952
}
957953

@@ -991,24 +987,26 @@ impl_install_tree (RpmOstreeTreeComposeContext *self, gboolean *out_changed,
991987
= (*self->treefile_rs)->get_repo_metadata_target ();
992988
if (repomd_target == rpmostreecxx::RepoMetadataTarget::Inline)
993989
{
994-
if (!g_hash_table_contains (self->metadata, "rpmostree.rpmmd-repos"))
990+
if (!g_variant_dict_contains (self->metadata, "rpmostree.rpmmd-repos"))
995991
{
996-
g_hash_table_insert (self->metadata, g_strdup ("rpmostree.rpmmd-repos"),
997-
rpmostree_context_get_rpmmd_repo_commit_metadata (self->corectx));
992+
g_autoptr (GVariant) meta
993+
= rpmostree_context_get_rpmmd_repo_commit_metadata (self->corectx);
994+
g_variant_dict_insert_value (self->metadata, "rpmostree.rpmmd-repos", meta);
998995
}
999996
}
1000997
else if (repomd_target == rpmostreecxx::RepoMetadataTarget::Detached)
1001998
{
1002-
if (!g_hash_table_contains (self->detached_metadata, "rpmostree.rpmmd-repos"))
999+
if (!g_variant_dict_contains (self->detached_metadata, "rpmostree.rpmmd-repos"))
10031000
{
1004-
g_hash_table_insert (self->detached_metadata, g_strdup ("rpmostree.rpmmd-repos"),
1005-
rpmostree_context_get_rpmmd_repo_commit_metadata (self->corectx));
1001+
g_autoptr (GVariant) meta
1002+
= rpmostree_context_get_rpmmd_repo_commit_metadata (self->corectx);
1003+
g_variant_dict_insert_value (self->detached_metadata, "rpmostree.rpmmd-repos", meta);
10061004
}
10071005
}
10081006
else
10091007
{
1010-
g_hash_table_remove (self->metadata, "rpmostree.rpmmd-repos");
1011-
g_hash_table_remove (self->detached_metadata, "rpmostree.rpmmd-repos");
1008+
g_variant_dict_remove (self->metadata, "rpmostree.rpmmd-repos");
1009+
g_variant_dict_remove (self->detached_metadata, "rpmostree.rpmmd-repos");
10121010
}
10131011

10141012
if (!inject_advisories (self, cancellable, error))
@@ -1057,8 +1055,7 @@ impl_install_tree (RpmOstreeTreeComposeContext *self, gboolean *out_changed,
10571055
}
10581056

10591057
/* Insert our input hash */
1060-
g_hash_table_replace (self->metadata, g_strdup ("rpmostree.inputhash"),
1061-
g_variant_ref_sink (g_variant_new_string (new_inputhash)));
1058+
g_variant_dict_insert (self->metadata, "rpmostree.inputhash", "s", new_inputhash);
10621059

10631060
*out_changed = TRUE;
10641061
return TRUE;
@@ -1120,8 +1117,7 @@ impl_commit_tree (RpmOstreeTreeComposeContext *self, GCancellable *cancellable,
11201117
GVariant *v = json_gvariant_deserialize (initramfs_args, "as", error);
11211118
if (!v)
11221119
return FALSE;
1123-
g_hash_table_insert (self->metadata, g_strdup ("rpmostree.initramfs-args"),
1124-
g_variant_ref_sink (v));
1120+
g_variant_dict_insert_value (self->metadata, "rpmostree.initramfs-args", v);
11251121
}
11261122

11271123
/* Convert metadata hash tables to GVariants */

src/app/rpmostree-composeutil.cxx

+27-17
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ rpmostree_composeutil_checksum (HyGoal goal, OstreeRepo *repo, const rpmostreecx
6464
}
6565

6666
gboolean
67-
rpmostree_composeutil_read_json_metadata (JsonNode *root, GHashTable *metadata, GError **error)
67+
rpmostree_composeutil_read_json_metadata (JsonNode *root, GVariantDict *metadata, GError **error)
6868
{
6969
g_autoptr (GVariant) jsonmetav = json_gvariant_deserialize (root, "a{sv}", error);
7070
if (!jsonmetav)
@@ -76,7 +76,7 @@ rpmostree_composeutil_read_json_metadata (JsonNode *root, GHashTable *metadata,
7676
char *key;
7777
GVariant *value;
7878
while (g_variant_iter_loop (&viter, "{sv}", &key, &value))
79-
g_hash_table_replace (metadata, g_strdup (key), g_variant_ref (value));
79+
g_variant_dict_insert_value (metadata, key, value);
8080
}
8181

8282
return TRUE;
@@ -86,7 +86,7 @@ rpmostree_composeutil_read_json_metadata (JsonNode *root, GHashTable *metadata,
8686
* to a hash table of a{sv}; suitable for further extension.
8787
*/
8888
gboolean
89-
rpmostree_composeutil_read_json_metadata_from_file (const char *path, GHashTable *metadata,
89+
rpmostree_composeutil_read_json_metadata_from_file (const char *path, GVariantDict *metadata,
9090
GError **error)
9191
{
9292
const char *errprefix = glnx_strjoina ("While parsing JSON file ", path);
@@ -101,19 +101,31 @@ rpmostree_composeutil_read_json_metadata_from_file (const char *path, GHashTable
101101
}
102102

103103
static GVariantBuilder *
104-
metadata_conversion_start (GHashTable *metadata)
104+
variant_dict_to_builder (GVariantDict *metadata)
105105
{
106-
GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
107-
108-
GLNX_HASH_TABLE_FOREACH_KV (metadata, const char *, strkey, GVariant *, v)
109-
g_variant_builder_add (builder, "{sv}", strkey, v);
106+
bool found_value = false;
107+
g_autoptr (GVariant) final_metadata = g_variant_ref_sink (g_variant_dict_end (metadata));
108+
GVariantIter viter;
109+
g_variant_iter_init (&viter, final_metadata);
110+
char *key;
111+
GVariant *value;
112+
g_autoptr (GVariantBuilder) builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
113+
while (g_variant_iter_loop (&viter, "{sv}", &key, &value))
114+
{
115+
found_value = true;
116+
g_variant_builder_add (builder, "{sv}", key, value);
117+
}
110118

111-
return builder;
119+
if (found_value)
120+
return util::move_nullify (builder);
121+
return NULL;
112122
}
113123

114124
static GVariant *
115125
metadata_conversion_end (GVariantBuilder *builder)
116126
{
127+
if (!builder)
128+
return NULL;
117129
g_autoptr (GVariant) ret = g_variant_ref_sink (g_variant_builder_end (builder));
118130
/* Canonicalize to big endian, like OSTree does. Without this, any numbers
119131
* we place in the metadata will be unreadable since clients won't know
@@ -126,9 +138,11 @@ metadata_conversion_end (GVariantBuilder *builder)
126138

127139
/* Convert hash table of metadata into finalized GVariant */
128140
GVariant *
129-
rpmostree_composeutil_finalize_metadata (GHashTable *metadata, int rootfs_dfd, GError **error)
141+
rpmostree_composeutil_finalize_metadata (GVariantDict *metadata, int rootfs_dfd, GError **error)
130142
{
131-
g_autoptr (GVariantBuilder) builder = metadata_conversion_start (metadata);
143+
g_autoptr (GVariantBuilder) builder = variant_dict_to_builder (metadata);
144+
if (!builder)
145+
builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
132146

133147
/* include list of packages in rpmdb; this is used client-side for easily previewing
134148
* pending updates. once we only support unified core composes, this can easily be much
@@ -143,13 +157,9 @@ rpmostree_composeutil_finalize_metadata (GHashTable *metadata, int rootfs_dfd, G
143157

144158
/* Convert hash table of metadata into finalized GVariant */
145159
GVariant *
146-
rpmostree_composeutil_finalize_detached_metadata (GHashTable *detached_metadata)
160+
rpmostree_composeutil_finalize_detached_metadata (GVariantDict *detached_metadata)
147161
{
148-
/* canonicalize empty detached metadata to NULL */
149-
if (g_hash_table_size (detached_metadata) == 0)
150-
return NULL;
151-
152-
g_autoptr (GVariantBuilder) builder = metadata_conversion_start (detached_metadata);
162+
g_autoptr (GVariantBuilder) builder = variant_dict_to_builder (detached_metadata);
153163
return metadata_conversion_end (builder);
154164
}
155165

src/app/rpmostree-composeutil.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,16 @@ gboolean rpmostree_composeutil_checksum (HyGoal goal, OstreeRepo *repo,
3131
const rpmostreecxx::Treefile &tf, JsonObject *treefile,
3232
char **out_checksum, GError **error);
3333

34-
gboolean rpmostree_composeutil_read_json_metadata (JsonNode *root, GHashTable *metadata,
34+
gboolean rpmostree_composeutil_read_json_metadata (JsonNode *root, GVariantDict *metadata,
3535
GError **error);
36-
gboolean rpmostree_composeutil_read_json_metadata_from_file (const char *path, GHashTable *metadata,
36+
gboolean rpmostree_composeutil_read_json_metadata_from_file (const char *path,
37+
GVariantDict *metadata,
3738
GError **error);
3839

39-
GVariant *rpmostree_composeutil_finalize_metadata (GHashTable *metadata, int rootfs_dfd,
40+
GVariant *rpmostree_composeutil_finalize_metadata (GVariantDict *metadata, int rootfs_dfd,
4041
GError **error);
4142

42-
GVariant *rpmostree_composeutil_finalize_detached_metadata (GHashTable *detached_metadata);
43+
GVariant *rpmostree_composeutil_finalize_detached_metadata (GVariantDict *detached_metadata);
4344

4445
gboolean rpmostree_composeutil_write_composejson (OstreeRepo *repo, const char *path,
4546
const OstreeRepoTransactionStats *stats,

0 commit comments

Comments
 (0)