Beispiel #1
0
/**
 * hif_state_get_child:
 **/
HifState *
hif_state_get_child (HifState *state)
{
	HifState *child = NULL;

	g_return_val_if_fail (HIF_IS_STATE (state), NULL);

	/* do we care */
	if (!state->priv->report_progress) {
		child = state;
		goto out;
	}

	/* already set child */
	if (state->priv->child != NULL) {
		g_signal_handler_disconnect (state->priv->child,
					     state->priv->percentage_child_id);
		g_signal_handler_disconnect (state->priv->child,
					     state->priv->allow_cancel_child_id);
		g_signal_handler_disconnect (state->priv->child,
					     state->priv->action_child_id);
		g_signal_handler_disconnect (state->priv->child,
					     state->priv->package_progress_child_id);
		g_signal_handler_disconnect (state->priv->child,
					     state->priv->notify_speed_child_id);
		g_object_unref (state->priv->child);
	}

	/* connect up signals */
	child = hif_state_new ();
	child->priv->parent = state; /* do not ref! */
	state->priv->child = child;
	state->priv->percentage_child_id =
		g_signal_connect (child, "percentage-changed",
				  G_CALLBACK (hif_state_child_percentage_changed_cb),
				  state);
	state->priv->allow_cancel_child_id =
		g_signal_connect (child, "allow-cancel-changed",
				  G_CALLBACK (hif_state_child_allow_cancel_changed_cb),
				  state);
	state->priv->action_child_id =
		g_signal_connect (child, "action-changed",
				  G_CALLBACK (hif_state_child_action_changed_cb),
				  state);
	state->priv->package_progress_child_id =
		g_signal_connect (child, "package-progress-changed",
				  G_CALLBACK (hif_state_child_package_progress_changed_cb),
				  state);
	state->priv->notify_speed_child_id =
		g_signal_connect (child, "notify::speed",
				  G_CALLBACK (hif_state_child_notify_speed_cb),
				  state);

	/* reset child */
	child->priv->current = 0;
	child->priv->last_percentage = 0;

	/* save so we can recover after child has done */
	child->priv->action = state->priv->action;
	state->priv->child_action = state->priv->action;

	/* set cancellable, creating if required */
	if (state->priv->cancellable == NULL)
		state->priv->cancellable = g_cancellable_new ();
	hif_state_set_cancellable (child, state->priv->cancellable);

	/* set the profile state */
	hif_state_set_enable_profile (child,
				      state->priv->enable_profile);
out:
	return child;
}
static gboolean
install_packages_in_root (RpmOstreeTreeComposeContext  *self,
                          RpmOstreeContext *ctx,
                          JsonObject      *treedata,
                          GFile           *yumroot,
                          char           **packages,
                          gboolean        *out_unmodified,
                          char           **out_new_inputhash,
                          GCancellable    *cancellable,
                          GError         **error)
{
  gboolean ret = FALSE;
  guint progress_sigid;
  GFile *contextdir = self->treefile_context_dirs->pdata[0];
  g_autoptr(RpmOstreeInstall) hifinstall = { 0, };
  HifContext *hifctx;
  gs_free char *ret_new_inputhash = NULL;
  g_autoptr(GKeyFile) treespec = g_key_file_new ();
  JsonArray *enable_repos = NULL;
  JsonArray *add_files = NULL;

  /* TODO - uncomment this once we have SELinux working */
#if 0
  g_autofree char *cache_repo_pathstr = glnx_fdrel_abspath (self->cachedir_dfd, "repo");
  g_autoptr(GFile) cache_repo_path = g_file_new_for_path (cache_repo_pathstr);
  glnx_unref_object OstreeRepo *ostreerepo = ostree_repo_new (cache_repo_path);

  if (!g_file_test (cache_repo_pathstr, G_FILE_TEST_EXISTS))
    {
      if (!ostree_repo_create (ostreerepo, OSTREE_REPO_MODE_BARE_USER, cancellable, error))
        goto out;
    }
#endif

  hifctx = rpmostree_context_get_hif (ctx);
  if (opt_proxy)
    hif_context_set_http_proxy (hifctx, opt_proxy);

  hif_context_set_repo_dir (hifctx, gs_file_get_path_cached (contextdir));

  g_key_file_set_string (treespec, "tree", "ref", self->ref);
  g_key_file_set_string_list (treespec, "tree", "packages", (const char *const*)packages, g_strv_length (packages));

  /* Some awful code to translate between JSON and GKeyFile */
  if (json_object_has_member (treedata, "install-langs"))
    {
      JsonArray *a = json_object_get_array_member (treedata, "install-langs");
      if (!set_keyfile_string_array_from_json (treespec, "tree", "install-langs", a, error))
        goto out;
    }

  /* Bind the json \"repos\" member to the hif state, which looks at the
   * enabled= member of the repos file.  By default we forcibly enable
   * only repos which are specified, ignoring the enabled= flag.
   */
  if (!json_object_has_member (treedata, "repos"))
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Treefile is missing required \"repos\" member");
      goto out;
    }

  enable_repos = json_object_get_array_member (treedata, "repos");

  if (!set_keyfile_string_array_from_json (treespec, "tree", "repos", enable_repos, error))
    goto out;

  { gboolean docs = TRUE;

    if (!_rpmostree_jsonutil_object_get_optional_boolean_member (treedata,
                                                                 "documentation",
                                                                 &docs,
                                                                 error))
      goto out;

    if (!docs)
      g_key_file_set_boolean (treespec, "tree", "documentation", FALSE);
  }

  { g_autoptr(GError) tmp_error = NULL;
    g_autoptr(RpmOstreeTreespec) treespec_value = rpmostree_treespec_new_from_keyfile (treespec, &tmp_error);
    g_assert_no_error (tmp_error);
    
    if (!rpmostree_context_setup (ctx, gs_file_get_path_cached (yumroot), "/", treespec_value,
                                  cancellable, error))
      goto out;
  }

  /* --- Downloading metadata --- */
  if (!rpmostree_context_download_metadata (ctx, cancellable, error))
    goto out;

  if (!rpmostree_context_prepare_install (ctx, &hifinstall, cancellable, error))
    goto out;

  if (json_object_has_member (treedata, "add-files"))
    add_files = json_object_get_array_member (treedata, "add-files");

  /* FIXME - just do a depsolve here before we compute download requirements */
  if (!compute_checksum_from_treefile_and_goal (self, hif_context_get_goal (hifctx),
                                                contextdir, add_files,
                                                &ret_new_inputhash, error))
    goto out;

  /* Only look for previous checksum if caller has passed *out_unmodified */
  if (self->previous_checksum && out_unmodified != NULL)
    {
      gs_unref_variant GVariant *commit_v = NULL;
      gs_unref_variant GVariant *commit_metadata = NULL;
      const char *previous_inputhash = NULL;
      
      if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_COMMIT,
                                     self->previous_checksum,
                                     &commit_v, error))
        goto out;

      commit_metadata = g_variant_get_child_value (commit_v, 0);
      if (g_variant_lookup (commit_metadata, "rpmostree.inputhash", "&s", &previous_inputhash))
        {
          if (strcmp (previous_inputhash, ret_new_inputhash) == 0)
            {
              *out_unmodified = TRUE;
              ret = TRUE;
              goto out;
            }
        }
      else
        g_print ("Previous commit found, but without rpmostree.inputhash metadata key\n");
    }

  if (opt_dry_run)
    {
      ret = TRUE;
      goto out;
    }

  /* --- Downloading packages --- */
  if (!rpmostree_context_download (ctx, hifinstall, cancellable, error))
    goto out;
  
  { g_auto(GLnxConsoleRef) console = { 0, };
    gs_unref_object HifState *hifstate = hif_state_new ();

    progress_sigid = g_signal_connect (hifstate, "percentage-changed",
                                     G_CALLBACK (on_hifstate_percentage_changed), 
                                     "Installing packages:");

    glnx_console_lock (&console);

    if (!hif_transaction_commit (hif_context_get_transaction (hifctx),
                                 hif_context_get_goal (hifctx),
                                 hifstate,
                                 error))
      goto out;

    g_signal_handler_disconnect (hifstate, progress_sigid);
  }
      
  ret = TRUE;
  if (out_unmodified)
    *out_unmodified = FALSE;
  gs_transfer_out_value (out_new_inputhash, &ret_new_inputhash);
 out:
  return ret;
}