Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compose: Factor out helper for writing composejson #1636

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 15 additions & 85 deletions src/app/rpmostree-compose-builtin-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -894,104 +894,34 @@ impl_commit_tree (RpmOstreeTreeComposeContext *self,
cancellable, error))
return FALSE;
}
g_print ("%s => %s\n", self->ref, new_revision);
g_variant_builder_add (&composemeta_builder, "{sv}", "ref", g_variant_new_string (self->ref));
}
else
g_print ("Wrote commit: %s\n", new_revision);

OstreeRepoTransactionStats stats = { 0, };
OstreeRepoTransactionStats *statsp = NULL;

if (use_txn)
{
OstreeRepoTransactionStats stats = { 0, };
if (!ostree_repo_commit_transaction (self->repo, &stats, cancellable, error))
return glnx_prefix_error (error, "Commit");

g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-n-metadata-total",
g_variant_new_uint32 (stats.metadata_objects_total));
g_print ("Metadata Total: %u\n", stats.metadata_objects_total);

g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-n-metadata-written",
g_variant_new_uint32 (stats.metadata_objects_written));
g_print ("Metadata Written: %u\n", stats.metadata_objects_written);

g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-n-content-total",
g_variant_new_uint32 (stats.content_objects_total));
g_print ("Content Total: %u\n", stats.content_objects_total);

g_print ("Content Written: %u\n", stats.content_objects_written);
g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-n-content-written",
g_variant_new_uint32 (stats.content_objects_written));

g_print ("Content Bytes Written: %" G_GUINT64_FORMAT "\n", stats.content_bytes_written);
g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-content-bytes-written",
g_variant_new_uint64 (stats.content_bytes_written));
statsp = &stats;
}
g_print ("Wrote commit: %s\n", new_revision);
g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-commit", g_variant_new_string (new_revision));
/* Since JavaScript doesn't have 64 bit integers and hence neither does JSON,
* store this as a string:
* https://stackoverflow.com/questions/10286204/the-right-json-date-format
* */
{ guint64 commit_ts = ostree_commit_get_timestamp (new_commit);
g_autofree char *commit_ts_iso_8601 = rpmostree_timestamp_str_from_unix_utc (commit_ts);
g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-timestamp", g_variant_new_string (commit_ts_iso_8601));
}
const char *commit_version = NULL;
(void)g_variant_lookup (new_commit_inline_meta, OSTREE_COMMIT_META_KEY_VERSION, "&s", &commit_version);
if (commit_version)
g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-version", g_variant_new_string (commit_version));

const char *inputhash = NULL;
(void)g_variant_lookup (new_commit_inline_meta, "rpmostree.inputhash", "&s", &inputhash);
/* We may not have the inputhash in the split-up installroot case */
if (inputhash)
g_variant_builder_add (&composemeta_builder, "{sv}", "rpm-ostree-inputhash", g_variant_new_string (inputhash));
if (parent_revision)
g_variant_builder_add (&composemeta_builder, "{sv}", "ostree-parent-commit", g_variant_new_string (parent_revision));

if (!rpmostree_composeutil_write_composejson (self->repo,
opt_write_composejson_to, statsp,
new_revision, new_commit,
&composemeta_builder,
error))
return FALSE;

if (opt_write_commitid_to)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think this slightly changes the semantics of --write-commitid-to though. Before it would override ref, but now we're doing both. That's likely to cause issues in e.g. pungi, which does the ref update as a separate step.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a test for that:

# --write-commitid-to should not set the ref
if ostree --repo=${repobuild} rev-parse ${treeref}; then
    fatal "Found ${treeref} ?"
fi
echo "ok ref not written"

which is passing. I think the diff is just misleading. If you look at the logic above, we're still doing:

  /* --write-commitid-to overrides writing the ref */
  if (self->ref && !opt_write_commitid_to)
    {
      if (use_txn)
        ostree_repo_transaction_set_ref (self->repo, NULL, self->ref, new_revision);
      else
        {
          if (!ostree_repo_set_ref_immediate (self->repo, NULL, self->ref, new_revision,
                                              cancellable, error))
            return FALSE;
        }
    }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh yeah, you're right. I misread it. Although, this chunk now is no longer overridden by --write-commitid-to, right?

if (self->ref)
  {
     g_print ("%s => %s\n", self->ref, new_revision);
     g_variant_builder_add (&composemeta_builder, "{sv}", "ref", g_variant_new_string (self->ref));
  }

So now, we're always printing that => line and inserting the ref key in the JSON even if we didn't actually update the ref, which is a bit misleading.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, updated ⬇️

{
if (!g_file_set_contents (opt_write_commitid_to, new_revision, -1, error))
return glnx_prefix_error (error, "While writing to '%s'", opt_write_commitid_to);
}
else if (self->ref)
{
g_print ("%s => %s\n", self->ref, new_revision);
g_variant_builder_add (&composemeta_builder, "{sv}", "ref", g_variant_new_string (self->ref));
}

if (opt_write_composejson_to && parent_revision)
{
g_autoptr(GVariant) diffv = NULL;
if (!rpm_ostree_db_diff_variant (self->repo, parent_revision, new_revision,
FALSE, &diffv, cancellable, error))
return FALSE;
g_variant_builder_add (&composemeta_builder, "{sv}", "pkgdiff", diffv);
}

if (opt_write_composejson_to)
{
g_autoptr(GVariant) composemeta_v = g_variant_builder_end (&composemeta_builder);
JsonNode *composemeta_node = json_gvariant_serialize (composemeta_v);
glnx_unref_object JsonGenerator *generator = json_generator_new ();
json_generator_set_root (generator, composemeta_node);

char *dnbuf = strdupa (opt_write_composejson_to);
const char *dn = dirname (dnbuf);
g_auto(GLnxTmpfile) tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, dn, O_WRONLY | O_CLOEXEC,
&tmpf, error))
return FALSE;
g_autoptr(GOutputStream) out = g_unix_output_stream_new (tmpf.fd, FALSE);
/* See also similar code in status.c */
if (json_generator_to_stream (generator, out, NULL, error) <= 0
|| (error != NULL && *error != NULL))
return FALSE;

/* World readable to match --write-commitid-to which uses umask */
if (!glnx_fchmod (tmpf.fd, 0644, error))
return FALSE;

if (!glnx_link_tmpfile_at (&tmpf, GLNX_LINK_TMPFILE_REPLACE,
AT_FDCWD, opt_write_composejson_to, error))
return FALSE;
}

return TRUE;
}
Expand Down
98 changes: 98 additions & 0 deletions src/app/rpmostree-composeutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "rpmostree-core.h"
#include "rpmostree-json-parsing.h"
#include "rpmostree-rojig-build.h"
#include "rpmostree-package-variants.h"
#include "rpmostree-libbuiltin.h"
#include "rpmostree-rpm-util.h"
#include "rpmostree-rust.h"
Expand Down Expand Up @@ -349,3 +350,100 @@ rpmostree_composeutil_finalize_metadata (GHashTable *metadata,

return g_steal_pointer (&ret);
}

/* Implements --write-composejson-to, and also prints values.
* If `path` is NULL, we'll just print some data.
*/
gboolean
rpmostree_composeutil_write_composejson (OstreeRepo *repo,
const char *path,
const OstreeRepoTransactionStats *stats,
const char *new_revision,
GVariant *new_commit,
GVariantBuilder *builder,
GError **error)
{
g_autoptr(GVariant) new_commit_inline_meta = g_variant_get_child_value (new_commit, 0);

if (stats)
{
g_variant_builder_add (builder, "{sv}", "ostree-n-metadata-total",
g_variant_new_uint32 (stats->metadata_objects_total));
g_print ("Metadata Total: %u\n", stats->metadata_objects_total);

g_variant_builder_add (builder, "{sv}", "ostree-n-metadata-written",
g_variant_new_uint32 (stats->metadata_objects_written));
g_print ("Metadata Written: %u\n", stats->metadata_objects_written);

g_variant_builder_add (builder, "{sv}", "ostree-n-content-total",
g_variant_new_uint32 (stats->content_objects_total));
g_print ("Content Total: %u\n", stats->content_objects_total);

g_print ("Content Written: %u\n", stats->content_objects_written);
g_variant_builder_add (builder, "{sv}", "ostree-n-content-written",
g_variant_new_uint32 (stats->content_objects_written));

g_print ("Content Bytes Written: %" G_GUINT64_FORMAT "\n", stats->content_bytes_written);
g_variant_builder_add (builder, "{sv}", "ostree-content-bytes-written",
g_variant_new_uint64 (stats->content_bytes_written));
}
g_variant_builder_add (builder, "{sv}", "ostree-commit", g_variant_new_string (new_revision));
const char *commit_version = NULL;
(void)g_variant_lookup (new_commit_inline_meta, OSTREE_COMMIT_META_KEY_VERSION, "&s", &commit_version);
if (commit_version)
g_variant_builder_add (builder, "{sv}", "ostree-version", g_variant_new_string (commit_version));
/* Since JavaScript doesn't have 64 bit integers and hence neither does JSON,
* store this as a string:
* https://stackoverflow.com/questions/10286204/the-right-json-date-format
* */
{ guint64 commit_ts = ostree_commit_get_timestamp (new_commit);
g_autofree char *commit_ts_iso_8601 = rpmostree_timestamp_str_from_unix_utc (commit_ts);
g_variant_builder_add (builder, "{sv}", "ostree-timestamp", g_variant_new_string (commit_ts_iso_8601));
}

const char *inputhash = NULL;
(void)g_variant_lookup (new_commit_inline_meta, "rpmostree.inputhash", "&s", &inputhash);
/* We may not have the inputhash in the split-up installroot case */
if (inputhash)
g_variant_builder_add (builder, "{sv}", "rpm-ostree-inputhash", g_variant_new_string (inputhash));

g_autofree char *parent_revision = ostree_commit_get_parent (new_commit);
if (path && parent_revision)
{
g_autoptr(GVariant) diffv = NULL;
if (!rpm_ostree_db_diff_variant (repo, parent_revision, new_revision,
FALSE, &diffv, NULL, error))
return FALSE;
g_variant_builder_add (builder, "{sv}", "pkgdiff", diffv);
}

if (path)
{
g_autoptr(GVariant) composemeta_v = g_variant_builder_end (builder);
JsonNode *composemeta_node = json_gvariant_serialize (composemeta_v);
glnx_unref_object JsonGenerator *generator = json_generator_new ();
json_generator_set_root (generator, composemeta_node);

char *dnbuf = strdupa (path);
const char *dn = dirname (dnbuf);
g_auto(GLnxTmpfile) tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, dn, O_WRONLY | O_CLOEXEC,
&tmpf, error))
return FALSE;
g_autoptr(GOutputStream) out = g_unix_output_stream_new (tmpf.fd, FALSE);
/* See also similar code in status.c */
if (json_generator_to_stream (generator, out, NULL, error) <= 0
|| (error != NULL && *error != NULL))
return FALSE;

/* World readable to match --write-commitid-to which uses umask */
if (!glnx_fchmod (tmpf.fd, 0644, error))
return FALSE;

if (!glnx_link_tmpfile_at (&tmpf, GLNX_LINK_TMPFILE_REPLACE,
AT_FDCWD, path, error))
return FALSE;
}

return TRUE;
}
8 changes: 8 additions & 0 deletions src/app/rpmostree-composeutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ rpmostree_composeutil_finalize_metadata (GHashTable *metadata,
int rootfs_dfd,
GError **error);

gboolean
rpmostree_composeutil_write_composejson (OstreeRepo *repo,
const char *path,
const OstreeRepoTransactionStats *stats,
const char *new_revision,
GVariant *new_commit,
GVariantBuilder *builder,
GError **error);

G_END_DECLS