Ejemplo n.º 1
0
static void
sysroot_output_cb (RpmOstreeOutputType type, void *data, void *opaque)
{
  RpmostreedSysroot *self = RPMOSTREED_SYSROOT (opaque);
  glnx_unref_object RpmostreedTransaction *transaction = NULL;

  transaction =
    rpmostreed_transaction_monitor_ref_active_transaction (self->transaction_monitor);

  if (!transaction)
    {
      rpmostree_output_default_handler (type, data, opaque);
      return;
    }

  switch (type)
  {
  case RPMOSTREE_OUTPUT_TASK_BEGIN:
    rpmostree_transaction_emit_task_begin (RPMOSTREE_TRANSACTION (transaction),
                                           ((RpmOstreeOutputTaskBegin*)data)->text);
    break;
  case RPMOSTREE_OUTPUT_TASK_END:
    rpmostree_transaction_emit_task_end (RPMOSTREE_TRANSACTION (transaction),
                                         ((RpmOstreeOutputTaskEnd*)data)->text);
    break;
  case RPMOSTREE_OUTPUT_PERCENT_PROGRESS:
    rpmostree_transaction_emit_percent_progress (RPMOSTREE_TRANSACTION (transaction),
                                                 ((RpmOstreeOutputPercentProgress*)data)->text,
                                                 ((RpmOstreeOutputPercentProgress*)data)->percentage);
    break;
  case RPMOSTREE_OUTPUT_PERCENT_PROGRESS_END:
    rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));
    break;
  }
}
Ejemplo n.º 2
0
static gboolean
sysroot_stdout_ready_cb (GPollableInputStream *pollable_stream,
                         StdoutClosure *closure)
{
  glnx_unref_object RpmostreedSysroot *sysroot = NULL;
  glnx_unref_object RpmostreedTransaction *transaction = NULL;
  GMemoryInputStream *memory_stream;
  GBufferedInputStream *buffered_stream;
  char buffer[1024];
  gconstpointer stream_buffer;
  gsize stream_buffer_size;
  gsize total_bytes_read = 0;
  gboolean have_line = FALSE;
  GError *local_error = NULL;

  sysroot = g_weak_ref_get (&closure->sysroot);
  if (sysroot != NULL)
    transaction = rpmostreed_transaction_monitor_ref_active_transaction (sysroot->transaction_monitor);

  /* XXX Would very much like g_buffered_input_stream_fill_nonblocking().
   *     Much of this function is a clumsy and inefficient attempt to
   *     achieve the same thing.
   *
   *     See: https://bugzilla.gnome.org/726797
   */

  buffered_stream = G_BUFFERED_INPUT_STREAM (closure->data_stream);
  memory_stream = (GMemoryInputStream *) g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (buffered_stream));

  while (local_error == NULL)
    {
      gssize n_read;

      n_read = g_pollable_input_stream_read_nonblocking (pollable_stream,
                                                         buffer,
                                                         sizeof (buffer),
                                                         NULL, &local_error);

      if (n_read > 0)
        {
          /* XXX Gotta use GBytes so the data gets copied. */
          g_autoptr(GBytes) bytes = g_bytes_new (buffer, n_read);
          g_memory_input_stream_add_bytes (memory_stream, bytes);
          total_bytes_read += n_read;
        }
    }

  if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
    goto out;

  g_clear_error (&local_error);

read_another_line:

  /* Fill the buffered stream with the data we just put in the
   * memory stream, then peek at the buffer to see if it's safe
   * to call g_data_input_stream_read_line() without blocking.
   *
   * XXX Oye, there's gotta be an easier way to do this...
   */

  /* This should never fail since it's just reading from memory. */
  g_buffered_input_stream_fill (buffered_stream, total_bytes_read, NULL, NULL);

  stream_buffer = g_buffered_input_stream_peek_buffer (buffered_stream, &stream_buffer_size);
  have_line = (memchr (stream_buffer, '\n', stream_buffer_size) != NULL);

  if (have_line)
    {
      g_autofree char *line = NULL;
      gsize length;

      line = g_data_input_stream_read_line (closure->data_stream,
                                            &length, NULL, &local_error);

      if (local_error != NULL)
        goto out;

      /* If there's an active transaction, forward the line to the
       * transaction's owner through the "Message" signal.  Otherwise
       * dump it to the non-redirected standard output stream. */
      if (transaction != NULL)
        {
          rpmostree_transaction_emit_message (RPMOSTREE_TRANSACTION (transaction), line);
        }
      else
        {
          /* This is essentially puts(), don't care about errors. */
          g_output_stream_write_all (closure->real_stdout,
                                     line, length, NULL, NULL, NULL);
          g_output_stream_write_all (closure->real_stdout,
                                     "\n", 1, NULL, NULL, NULL);
        }

      goto read_another_line;
    }

out:
  if (local_error != NULL)
    {
      g_warning ("Failed to read stdout pipe: %s", local_error->message);
      g_clear_error (&local_error);
    }

  return G_SOURCE_CONTINUE;
}
static gboolean
package_diff_transaction_execute (RpmostreedTransaction *transaction,
                                  GCancellable *cancellable,
                                  GError **error)
{
  PackageDiffTransaction *self;
  OstreeSysroot *sysroot;

  glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
  glnx_unref_object OstreeAsyncProgress *progress = NULL;
  glnx_unref_object OstreeRepo *repo = NULL;
  g_autoptr(GKeyFile) origin = NULL;
  g_autofree gchar *origin_description = NULL;

  OstreeSysrootUpgraderPullFlags upgrader_flags = 0;
  gboolean upgrading = FALSE;
  gboolean changed = FALSE;
  gboolean ret = FALSE;

  self = (PackageDiffTransaction *) transaction;
  sysroot = rpmostreed_transaction_get_sysroot (transaction);
  upgrader = ostree_sysroot_upgrader_new_for_os (sysroot,
                                                 self->osname,
                                                 cancellable,
                                                 error);
  if (upgrader == NULL)
    goto out;

  if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
    goto out;

  origin = ostree_sysroot_upgrader_dup_origin (upgrader);

  /* Determine if we're upgrading before we set the refspec. */
  upgrading = (self->refspec == NULL && self->revision == NULL);

  if (self->refspec != NULL)
    {
      if (!change_upgrader_refspec (sysroot, upgrader,
                                    self->refspec, cancellable,
                                    NULL, NULL, error))
        goto out;
    }
  else if (origin != NULL)
    {
      self->refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
      if (self->refspec == NULL)
        {
          g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                               "Could not find refspec for booted deployment");
        }
    }
  else
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Booted deployment has no origin");
      goto out;
    }

  progress = ostree_async_progress_new ();
  rpmostreed_transaction_connect_download_progress (transaction, progress);
  rpmostreed_transaction_connect_signature_progress (transaction, repo);

  if (self->revision != NULL)
    {
      g_autofree char *checksum = NULL;
      g_autofree char *version = NULL;

      upgrader_flags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;

      if (!rpmostreed_parse_revision (self->revision,
                                      &checksum,
                                      &version,
                                      error))
        goto out;

      if (version != NULL)
        {
          rpmostreed_transaction_emit_message_printf (transaction,
                                                      "Resolving version '%s'",
                                                      version);

          if (!rpmostreed_repo_lookup_version (repo,
                                               self->refspec,
                                               version,
                                               progress,
                                               cancellable,
                                               &checksum,
                                               error))
            goto out;
        }

      g_key_file_set_string (origin, "origin", "override-commit", checksum);

      if (!ostree_sysroot_upgrader_set_origin (upgrader, origin,
                                               cancellable, error))
        goto out;
    }
  else if (upgrading)
    {
      if (g_key_file_remove_key (origin, "origin", "override-commit", NULL))
        {
          if (!ostree_sysroot_upgrader_set_origin (upgrader, origin,
                                                   cancellable, error))
            goto out;
        }
    }

  origin_description = ostree_sysroot_upgrader_get_origin_description (upgrader);
  if (origin_description != NULL)
    rpmostreed_transaction_emit_message_printf (transaction,
                                                "Updating from: %s",
                                                origin_description);

  if (!ostree_sysroot_upgrader_pull_one_dir (upgrader,
					     "/usr/share/rpm",
					     0, upgrader_flags,
					     progress,
					     &changed,
					     cancellable,
					     error))
    goto out;

  rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));

  if (!changed)
    {
      if (upgrading)
        rpmostreed_transaction_emit_message_printf (transaction,
                                                    "No upgrade available.");
      else
        rpmostreed_transaction_emit_message_printf (transaction,
                                                    "No change.");
    }

  ret = TRUE;
out:
  return ret;
}