packagekit/client/pk-console.c

2430 lines
77 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2007-2014 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <glib/gi18n.h>
#include <glib-unix.h>
#include <packagekit-glib2/packagekit.h>
#include <packagekit-glib2/packagekit-private.h>
#include <sys/types.h>
#include <pwd.h>
#include <locale.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#define PK_EXIT_CODE_SYNTAX_INVALID 3
#define PK_EXIT_CODE_FILE_NOT_FOUND 4
#define PK_EXIT_CODE_NOTHING_USEFUL 5
#define PK_EXIT_CODE_CANNOT_SETUP 6
#define PK_EXIT_CODE_TRANSACTION_FAILED 7
#define PK_CONSOLE_ERROR 1
typedef struct {
GCancellable *cancellable;
GMainLoop *loop;
PkBitfield roles;
PkControl *control;
PkProgressBar *progressbar;
PkTaskText *task;
gboolean is_console;
gint retval;
PkBitfield filters;
guint defered_status_id;
PkStatusEnum defered_status;
} PkConsoleCtx;
/**
* pk_strpad:
* @data: the input string
* @length: the desired length of the output string, with padding
*
* Returns the text padded to a length with spaces. If the string is
* longer than length then a longer string is returned.
*
* Return value: The padded string
**/
static gchar *
pk_strpad (const gchar *data, guint length)
{
gint size;
guint data_len;
g_autofree gchar *padding = NULL;
if (data == NULL)
return g_strnfill (length, ' ');
/* ITS4: ignore, only used for formatting */
data_len = strlen (data);
/* calculate */
size = (length - data_len);
if (size <= 0)
return g_strdup (data);
padding = g_strnfill (size, ' ');
return g_strdup_printf ("%s%s", data, padding);
}
static void
pk_console_package_cb (PkPackage *package, PkConsoleCtx *ctx)
{
PkInfoEnum info;
const gchar *package_id;
g_autofree gchar *info_pad = NULL;
g_autofree gchar *printable = NULL;
g_autofree gchar *printable_pad = NULL;
g_auto(GStrv) split = NULL;
/* ignore finished */
info = pk_package_get_info (package);
if (info == PK_INFO_ENUM_FINISHED)
return;
/* split */
package_id = pk_package_get_id (package);
split = pk_package_id_split (package_id);
if (split == NULL)
return;
/* make these all the same length */
info_pad = pk_strpad (pk_info_enum_to_localised_past (info), 12);
/* create printable */
printable = g_strdup_printf ("%s-%s.%s (%s)",
split[PK_PACKAGE_ID_NAME],
split[PK_PACKAGE_ID_VERSION],
split[PK_PACKAGE_ID_ARCH],
split[PK_PACKAGE_ID_DATA]);
/* don't pretty print */
if (!ctx->is_console) {
g_print ("%s %s\n", info_pad, printable);
return;
}
/* pad the name-version */
printable_pad = pk_strpad (printable, 60);
g_print ("%s\t%s\t%s\n", info_pad, printable_pad,
pk_package_get_summary (package));
}
static void
pk_console_transaction_cb (PkTransactionPast *item, PkConsoleCtx *ctx)
{
PkRoleEnum role;
const gchar *role_text;
gboolean succeeded;
guint duration;
guint i, lines_len;
guint uid;
struct passwd *pw;
g_autofree gchar *cmdline = NULL;
g_autofree gchar *data = NULL;
g_autofree gchar *tid = NULL;
g_autofree gchar *timespec = NULL;
g_auto(GStrv) lines = NULL;
/* get data */
g_object_get (item,
"role", &role,
"tid", &tid,
"timespec", &timespec,
"succeeded", &succeeded,
"duration", &duration,
"cmdline", &cmdline,
"uid", &uid,
"data", &data,
NULL);
role_text = pk_role_enum_to_string (role);
/* TRANSLATORS: this is an atomic transaction */
g_print ("%s: %s\n", _("Transaction"), tid);
/* TRANSLATORS: this is the time the transaction was started in system timezone */
g_print (" %s: %s\n", _("System time"), timespec);
/* TRANSLATORS: this is if the transaction succeeded or not */
g_print (" %s: %s\n", _("Succeeded"), succeeded ? _("True") : _("False"));
/* TRANSLATORS: this is the transactions role, e.g. "update-packages" */
g_print (" %s: %s\n", _("Role"), role_text);
/* only print if not null */
if (duration > 0) {
/* TRANSLATORS: this is The duration of the transaction */
g_print (" %s: %i %s\n", _("Duration"), duration, _("(seconds)"));
}
/* TRANSLATORS: this is The command line used to do the action */
g_print (" %s: %s\n", _("Command line"), cmdline);
/* TRANSLATORS: this is the user ID of the user that started the action */
g_print (" %s: %i\n", _("User ID"), uid);
/* query real name */
pw = getpwuid (uid);
if (pw != NULL) {
if (pw->pw_name != NULL) {
/* TRANSLATORS: this is the username, e.g. hughsie */
g_print (" %s: %s\n", _("Username"), pw->pw_name);
}
if (pw->pw_gecos != NULL) {
/* TRANSLATORS: this is the users real name, e.g. "Richard Hughes" */
g_print (" %s: %s\n", _("Real name"), pw->pw_gecos);
}
}
lines = g_strsplit (data, "\n", -1);
lines_len = g_strv_length (lines);
if (lines_len > 0) {
/* TRANSLATORS: these are packages touched by the transaction */
g_print (" %s\n", _("Affected packages:"));
} else {
/* TRANSLATORS: these are packages touched by the transaction */
g_print (" %s\n", _("Affected packages: None"));
}
for (i = 0; i < lines_len; i++) {
g_autofree gchar *package = NULL;
g_auto(GStrv) parts = NULL;
parts = g_strsplit (lines[i], "\t", 3);
package = pk_package_id_to_printable (parts[1]);
g_print (" - %s %s\n", parts[0], package);
}
}
static void
pk_console_distro_upgrade_cb (PkDistroUpgrade *item, gpointer user_data)
{
PkDistroUpgradeEnum state;
g_autofree gchar *name = NULL;
g_autofree gchar *summary = NULL;
/* get data */
g_object_get (item,
"name", &name,
"state", &state,
"summary", &summary,
NULL);
/* TRANSLATORS: this is the distro, e.g. Fedora 10 */
g_print ("%s: %s\n", _("Distribution"), name);
/* TRANSLATORS: this is type of update, stable or testing */
g_print (" %s: %s\n", _("Type"), pk_distro_upgrade_enum_to_string (state));
/* TRANSLATORS: this is any summary text describing the upgrade */
g_print (" %s: %s\n", _("Summary"), summary);
}
static void
pk_console_category_cb (PkCategory *item, gpointer user_data)
{
g_autofree gchar *name = NULL;
g_autofree gchar *cat_id = NULL;
g_autofree gchar *parent_id = NULL;
g_autofree gchar *summary = NULL;
g_autofree gchar *icon = NULL;
/* get data */
g_object_get (item,
"name", &name,
"cat_id", &cat_id,
"parent_id", &parent_id,
"summary", &summary,
"icon", &icon,
NULL);
/* TRANSLATORS: this is the group category name */
g_print ("%s: %s\n", _("Category"), name);
/* TRANSLATORS: this is group identifier */
g_print (" %s: %s\n", _("ID"), cat_id);
if (parent_id != NULL) {
/* TRANSLATORS: this is the parent group */
g_print (" %s: %s\n", _("Parent"), parent_id);
}
/* TRANSLATORS: this is the name of the parent group */
g_print (" %s: %s\n", _("Name"), name);
if (summary != NULL) {
/* TRANSLATORS: this is the summary of the group */
g_print (" %s: %s\n", _("Summary"), summary);
}
/* TRANSLATORS: this is preferred icon for the group */
g_print (" %s: %s\n", _("Icon"), icon);
}
static void
pk_console_update_detail_cb (PkUpdateDetail *item, gpointer data)
{
PkRestartEnum restart;
PkUpdateStateEnum state;
gchar *tmp;
g_autofree gchar *changelog = NULL;
g_autofree gchar *issued = NULL;
g_autofree gchar *package_id = NULL;
g_autofree gchar *package = NULL;
g_autofree gchar *updated = NULL;
g_autofree gchar *update_text = NULL;
g_auto(GStrv) bugzilla_urls = NULL;
g_auto(GStrv) cve_urls = NULL;
g_auto(GStrv) obsoletes = NULL;
g_auto(GStrv) updates = NULL;
g_auto(GStrv) vendor_urls = NULL;
/* get data */
g_object_get (item,
"package-id", &package_id,
"updates", &updates,
"obsoletes", &obsoletes,
"vendor-urls", &vendor_urls,
"bugzilla-urls", &bugzilla_urls,
"cve-urls", &cve_urls,
"restart", &restart,
"update-text", &update_text,
"changelog", &changelog,
"state", &state,
"issued", &issued,
"updated", &updated,
NULL);
/* TRANSLATORS: this is a header for the package that can be updated */
g_print ("%s\n", _("Details about the update:"));
/* create printable */
package = pk_package_id_to_printable (package_id);
/* TRANSLATORS: details about the update, package name and version */
g_print (" %s: %s\n", _("Package"), package);
if (updates != NULL) {
tmp = g_strjoinv (", ", updates);
/* TRANSLATORS: details about the update, any packages that
* this update updates */
g_print (" %s: %s\n", _("Updates"), tmp);
g_free (tmp);
}
if (obsoletes != NULL) {
tmp = g_strjoinv (", ", obsoletes);
/* TRANSLATORS: details about the update, any packages that
* this update obsoletes */
g_print (" %s: %s\n", _("Obsoletes"), tmp);
g_free (tmp);
}
if (vendor_urls != NULL) {
tmp = g_strjoinv (", ", vendor_urls);
/* TRANSLATORS: details about the update, the vendor URLs */
g_print (" %s: %s\n", _("Vendor"), tmp);
g_free (tmp);
}
if (bugzilla_urls != NULL) {
tmp = g_strjoinv (", ", bugzilla_urls);
/* TRANSLATORS: details about the update, the bugzilla URLs */
g_print (" %s: %s\n", _("Bugzilla"), tmp);
g_free (tmp);
}
if (cve_urls != NULL) {
tmp = g_strjoinv (", ", cve_urls);
/* TRANSLATORS: details about the update, the CVE URLs */
g_print (" %s: %s\n", _("CVE"), tmp);
g_free (tmp);
}
if (restart != PK_RESTART_ENUM_NONE) {
/* TRANSLATORS: details about the update, if the package
* requires a restart */
g_print (" %s: %s\n", _("Restart"), pk_restart_enum_to_string (restart));
}
if (update_text != NULL) {
/* TRANSLATORS: details about the update, any description of
* the update */
g_print (" %s: %s\n", _("Update text"), update_text);
}
if (changelog != NULL) {
/* TRANSLATORS: details about the update, the changelog for
* the package */
g_print (" %s: %s\n", _("Changes"), changelog);
}
if (state != PK_UPDATE_STATE_ENUM_UNKNOWN) {
/* TRANSLATORS: details about the update, the ongoing state
* of the update */
g_print (" %s: %s\n", _("State"), pk_update_state_enum_to_string (state));
}
if (issued != NULL) {
/* TRANSLATORS: details about the update, date the update
* was issued */
g_print (" %s: %s\n", _("Issued"), issued);
}
if (updated != NULL) {
/* TRANSLATORS: details about the update, date the update
* was updated */
g_print (" %s: %s\n", _("Updated"), updated);
}
}
static void
pk_console_repo_detail_cb (PkRepoDetail *item, gpointer data)
{
gchar *enabled_pad;
gchar *repo_pad;
gchar *repo_id;
gboolean enabled;
gchar *description;
/* get data */
g_object_get (item,
"repo-id", &repo_id,
"enabled", &enabled,
"description", &description,
NULL);
if (enabled) {
/* TRANSLATORS: if the repo is enabled */
enabled_pad = pk_strpad (_("Enabled"), 10);
} else {
/* TRANSLATORS: if the repo is disabled */
enabled_pad = pk_strpad (_("Disabled"), 10);
}
repo_pad = pk_strpad (repo_id, 25);
g_print (" %s %s %s\n", enabled_pad, repo_pad, description);
g_free (enabled_pad);
g_free (repo_pad);
g_free (repo_id);
g_free (description);
}
static void
pk_console_require_restart_cb (PkRequireRestart *item, gpointer data)
{
PkRestartEnum restart;
g_autofree gchar *package = NULL;
g_autofree gchar *package_id = NULL;
/* get data */
g_object_get (item,
"package-id", &package_id,
"restart", &restart,
NULL);
/* create printable */
package = pk_package_id_to_printable (package_id);
if (restart == PK_RESTART_ENUM_SYSTEM) {
/* TRANSLATORS: a package requires the system to be restarted */
g_print ("%s %s\n", _("System restart required by:"), package);
} else if (restart == PK_RESTART_ENUM_SESSION) {
/* TRANSLATORS: a package requires the session to be restarted */
g_print ("%s %s\n", _("Session restart required:"), package);
} else if (restart == PK_RESTART_ENUM_SECURITY_SYSTEM) {
/* TRANSLATORS: a package requires the system to be restarted
* due to a security update*/
g_print ("%s %s\n", _("System restart (security) required by:"), package);
} else if (restart == PK_RESTART_ENUM_SECURITY_SESSION) {
/* TRANSLATORS: a package requires the session to be restarted
* due to a security update */
g_print ("%s %s\n", _("Session restart (security) required:"), package);
} else if (restart == PK_RESTART_ENUM_APPLICATION) {
/* TRANSLATORS: a package requires the application to be restarted */
g_print ("%s %s\n", _("Application restart required by:"), package);
}
}
static void
pk_console_details_cb (PkDetails *item, gpointer data)
{
PkGroupEnum group;
guint64 size;
g_autofree gchar *description = NULL;
g_autofree gchar *license = NULL;
g_autofree gchar *package_id = NULL;
g_autofree gchar *package = NULL;
g_autofree gchar *summary = NULL;
g_autofree gchar *url = NULL;
/* get data */
g_object_get (item,
"package-id", &package_id,
"license", &license,
"description", &description,
"url", &url,
"summary", &summary,
"group", &group,
"size", &size,
NULL);
/* create printable */
package = pk_package_id_to_printable (package_id);
/* TRANSLATORS: This a list of details about the package */
g_print ("%s\n", _("Package description"));
g_print (" package: %s\n", package);
g_print (" summary: %s\n", summary);
g_print (" license: %s\n", license);
g_print (" group: %s\n", pk_group_enum_to_string (group));
g_print (" description: %s\n", description);
g_print (" size: %lu bytes\n", (long unsigned int) size);
g_print (" url: %s\n", url);
}
static void
pk_console_files_cb (PkFiles *item, gpointer data)
{
guint i;
gchar **files;
/* empty */
files = pk_files_get_files (item);
if (files == NULL || files[0] == NULL) {
/* TRANSLATORS: This where the package has no files */
g_print ("%s\n", _("No files"));
return;
}
/* TRANSLATORS: This a list files contained in the package */
g_print ("%s\n", _("Package files"));
for (i = 0; files[i] != NULL; i++)
g_print (" %s\n", files[i]);
}
static gboolean
pk_console_defer_status_update_cb (gpointer user_data)
{
PkConsoleCtx *ctx = (PkConsoleCtx *) user_data;
const gchar *text;
text = pk_status_enum_to_localised_text (ctx->defered_status);
pk_progress_bar_start (ctx->progressbar, text);
g_source_remove (ctx->defered_status_id);
ctx->defered_status_id = 0;
return FALSE;
}
static void
pk_console_defer_status_update (PkConsoleCtx *ctx, PkStatusEnum status)
{
if (ctx->defered_status_id > 0)
g_source_remove (ctx->defered_status_id);
ctx->defered_status = status;
ctx->defered_status_id = g_timeout_add (50,
pk_console_defer_status_update_cb,
ctx);
}
static void
pk_console_progress_cb (PkProgress *progress, PkProgressType type, gpointer data)
{
gint percentage;
PkStatusEnum status;
PkRoleEnum role;
const gchar *text;
guint64 transaction_flags;
PkConsoleCtx *ctx = (PkConsoleCtx *) data;
g_autofree gchar *package_id = NULL;
g_autofree gchar *printable = NULL;
/* role */
if (type == PK_PROGRESS_TYPE_ROLE) {
g_object_get (progress,
"role", &role,
"transaction-flags", &transaction_flags,
NULL);
if (role == PK_ROLE_ENUM_UNKNOWN)
return;
/* don't show the role when simulating */
if (ctx->defered_status != PK_STATUS_ENUM_UNKNOWN &&
pk_bitfield_contain (transaction_flags,
PK_TRANSACTION_FLAG_ENUM_SIMULATE))
return;
/* show new status on the bar */
text = pk_role_enum_to_localised_present (role);
if (!ctx->is_console) {
/* TRANSLATORS: the role is the point of the transaction,
* e.g. update-packages */
g_print ("%s:\t%s\n", _("Transaction"), text);
return;
}
pk_progress_bar_start (ctx->progressbar, text);
}
/* package-id */
if (type == PK_PROGRESS_TYPE_PACKAGE_ID) {
g_object_get (progress,
"package-id", &package_id,
NULL);
if (package_id == NULL)
return;
if (!ctx->is_console) {
/* create printable */
printable = pk_package_id_to_printable (package_id);
/* TRANSLATORS: the package that is being processed */
g_print ("%s:\t%s\n", _("Package"), printable);
return;
}
}
/* percentage */
if (type == PK_PROGRESS_TYPE_PERCENTAGE) {
g_object_get (progress,
"percentage", &percentage,
NULL);
if (!ctx->is_console) {
/* only print the 10's */
if (percentage % 10 != 0)
return;
/* TRANSLATORS: the percentage complete of the transaction */
g_print ("%s:\t%i\n", _("Percentage"), percentage);
return;
}
pk_progress_bar_set_percentage (ctx->progressbar, percentage);
}
/* status */
if (type == PK_PROGRESS_TYPE_STATUS) {
g_object_get (progress,
"role", &role,
"status", &status,
"transaction-flags", &transaction_flags,
NULL);
/* don't show finished multiple times in the output */
if (role == PK_ROLE_ENUM_RESOLVE &&
status == PK_STATUS_ENUM_FINISHED)
return;
/* show new status on the bar */
if (!ctx->is_console) {
text = pk_status_enum_to_localised_text (status);
/* TRANSLATORS: the status of the transaction (e.g. downloading) */
g_print ("%s: \t%s\n", _("Status"), text);
return;
}
/* defer most status actions for 50ms */
if (status != PK_STATUS_ENUM_FINISHED) {
if (pk_bitfield_contain (transaction_flags,
PK_TRANSACTION_FLAG_ENUM_SIMULATE)) {
/* don't show progress when doing the simulate pass */
pk_console_defer_status_update (ctx,
PK_STATUS_ENUM_TEST_COMMIT);
} else {
pk_console_defer_status_update (ctx, status);
}
} else {
text = pk_status_enum_to_localised_text (status);
pk_progress_bar_start (ctx->progressbar, text);
}
}
}
static void
pk_console_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
{
const gchar *filename;
gboolean ret;
GPtrArray *array;
PkPackageSack *sack;
PkRestartEnum restart;
PkRoleEnum role;
PkConsoleCtx *ctx = (PkConsoleCtx *) data;
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(PkError) error_code = NULL;
g_autoptr(PkResults) results = NULL;
/* no more progress */
if (ctx->is_console) {
pk_progress_bar_end (ctx->progressbar);
} else {
/* TRANSLATORS: the results from the transaction */
g_print ("%s\n", _("Results:"));
}
/* get the results */
results = pk_task_generic_finish (PK_TASK (ctx->task), res, &error);
if (results == NULL) {
/* TRANSLATORS: we failed to get any results, which is pretty
* fatal in my book */
g_print ("%s: %s\n", _("Fatal error"), error->message);
switch (error->code - 0xff) {
case PK_ERROR_ENUM_ALL_PACKAGES_ALREADY_INSTALLED:
case PK_ERROR_ENUM_REPO_NOT_AVAILABLE:
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
break;
default:
ctx->retval = PK_EXIT_CODE_TRANSACTION_FAILED;
break;
}
goto out;
}
/* get the role */
g_object_get (G_OBJECT(results), "role", &role, NULL);
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
/* print an error */
if (role == PK_ROLE_ENUM_UPDATE_PACKAGES &&
pk_error_get_code (error_code) == PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE) {
/* TRANSLATORS: the user asked to update everything,
* but there is nothing that can be updated */
g_print ("%s\n", _("There are no packages to update."));
} else {
/* TRANSLATORS: the transaction failed in a way we could
* not expect */
g_print ("%s: %s, %s\n", _("The transaction failed"), pk_error_enum_to_string (pk_error_get_code (error_code)), pk_error_get_details (error_code));
}
/* special case */
if (pk_error_get_code (error_code) == PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE)
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
goto out;
}
/* get the sack */
sack = pk_results_get_package_sack (results);
pk_package_sack_sort (sack, PK_PACKAGE_SACK_SORT_TYPE_NAME);
array = pk_package_sack_get_array (sack);
/* package */
filename = g_object_get_data (G_OBJECT (ctx->task), "PkConsole:list-create-filename");
if (!ctx->is_console ||
(role != PK_ROLE_ENUM_INSTALL_PACKAGES &&
role != PK_ROLE_ENUM_UPDATE_PACKAGES &&
role != PK_ROLE_ENUM_REMOVE_PACKAGES &&
filename == NULL)) {
g_ptr_array_foreach (array, (GFunc) pk_console_package_cb, ctx);
}
/* special case */
if (array->len == 0 &&
(role == PK_ROLE_ENUM_GET_UPDATES ||
role == PK_ROLE_ENUM_UPDATE_PACKAGES)) {
/* TRANSLATORS: print a message when there are no updates */
g_print ("%s\n", _("There are no updates available at this time."));
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
}
g_ptr_array_unref (array);
g_object_unref (sack);
/* transaction */
array = pk_results_get_transaction_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_transaction_cb, ctx);
/* special case */
if (array->len == 0 && role == PK_ROLE_ENUM_GET_OLD_TRANSACTIONS)
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
g_ptr_array_unref (array);
/* distro_upgrade */
array = pk_results_get_distro_upgrade_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_distro_upgrade_cb, ctx);
/* special case */
if (array->len == 0 && role == PK_ROLE_ENUM_GET_DISTRO_UPGRADES) {
g_print ("%s\n", _("There are no upgrades available at this time."));
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
}
g_ptr_array_unref (array);
/* category */
array = pk_results_get_category_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_category_cb, ctx);
/* special case */
if (array->len == 0 && role == PK_ROLE_ENUM_GET_CATEGORIES)
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
g_ptr_array_unref (array);
/* update_detail */
array = pk_results_get_update_detail_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_update_detail_cb, ctx);
/* special case */
if (array->len == 0 && role == PK_ROLE_ENUM_GET_UPDATE_DETAIL)
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
g_ptr_array_unref (array);
/* repo_detail */
array = pk_results_get_repo_detail_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_repo_detail_cb, ctx);
/* special case */
if (array->len == 0 && role == PK_ROLE_ENUM_GET_REPO_LIST)
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
g_ptr_array_unref (array);
/* require_restart */
array = pk_results_get_require_restart_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_require_restart_cb, ctx);
g_ptr_array_unref (array);
/* details */
array = pk_results_get_details_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_details_cb, ctx);
/* special case */
if (array->len == 0 && role == PK_ROLE_ENUM_GET_DETAILS)
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
g_ptr_array_unref (array);
/* don't print files if we are DownloadPackages */
if (role != PK_ROLE_ENUM_DOWNLOAD_PACKAGES) {
array = pk_results_get_files_array (results);
g_ptr_array_foreach (array, (GFunc) pk_console_files_cb, ctx);
g_ptr_array_unref (array);
}
/* is there any restart to notify the user? */
restart = pk_results_get_require_restart_worst (results);
if (restart == PK_RESTART_ENUM_SYSTEM) {
/* TRANSLATORS: a package needs to restart their system */
g_print ("%s\n", _("Please restart the computer to complete the update."));
} else if (restart == PK_RESTART_ENUM_SESSION) {
/* TRANSLATORS: a package needs to restart the session */
g_print ("%s\n", _("Please logout and login to complete the update."));
} else if (restart == PK_RESTART_ENUM_SECURITY_SYSTEM) {
/* TRANSLATORS: a package needs to restart their system (due to security) */
g_print ("%s\n", _("Please restart the computer to complete the update as important security updates have been installed."));
} else if (restart == PK_RESTART_ENUM_SECURITY_SESSION) {
/* TRANSLATORS: a package needs to restart the session (due to security) */
g_print ("%s\n", _("Please logout and login to complete the update as important security updates have been installed."));
}
/* write the sack to disk */
if (role == PK_ROLE_ENUM_GET_PACKAGES && filename != NULL) {
file = g_file_new_for_path (filename);
ret = pk_package_sack_to_file (sack, file, &error);
if (!ret) {
g_print ("%s: %s\n", _("Fatal error"), error->message);
ctx->retval = PK_EXIT_CODE_TRANSACTION_FAILED;
goto out;
}
}
out:
g_main_loop_quit (ctx->loop);
}
static gchar *
pk_console_resolve_package (PkConsoleCtx *ctx, const gchar *package_name, GError **error)
{
const gchar *package_id_tmp;
gchar *package_id = NULL;
gboolean valid;
guint i;
PkPackage *package;
g_autoptr(GPtrArray) array = NULL;
g_autoptr(PkError) error_code = NULL;
g_autoptr(PkResults) results = NULL;
g_auto(GStrv) tmp = NULL;
/* have we passed a complete package_id? */
valid = pk_package_id_check (package_name);
if (valid)
return g_strdup (package_name);
/* split */
tmp = g_strsplit (package_name, ",", -1);
/* get the list of possibles */
results = pk_client_resolve (PK_CLIENT (ctx->task),
ctx->filters, tmp,
ctx->cancellable,
pk_console_progress_cb, ctx,
error);
if (results == NULL)
return NULL;
/* check error code */
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_set_error_literal (error,
PK_CONSOLE_ERROR,
pk_error_get_code (error_code),
pk_error_get_details (error_code));
return NULL;
}
/* nothing found */
array = pk_results_get_package_array (results);
if (array->len == 0) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
"could not find %s", package_name);
return NULL;
}
/* just one thing found */
if (array->len == 1) {
package = g_ptr_array_index (array, 0);
g_object_get (package,
"package-id", &package_id,
NULL);
return g_strdup (pk_package_get_id (package));
}
/* TRANSLATORS: more than one package could be found that matched,
* to follow is a list of possible packages */
g_print ("%s\n", _("More than one package matches:"));
for (i = 0; i < array->len; i++) {
g_autofree gchar *printable = NULL;
g_auto(GStrv) split = NULL;
package = g_ptr_array_index (array, i);
package_id_tmp = pk_package_get_id (package);
split = pk_package_id_split (package_id_tmp);
printable = pk_package_id_to_printable (package_id_tmp);
g_print ("%i. %s [%s]\n", i+1, printable, split[PK_PACKAGE_ID_DATA]);
}
/* TRANSLATORS: This finds out which package in the list to use */
i = pk_console_get_number (_("Please choose the correct package: "), array->len);
if (i == 0) {
g_set_error_literal (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_TRANSACTION_CANCELLED,
"User aborted selection");
return NULL;
}
package = g_ptr_array_index (array, i - 1);
return g_strdup (pk_package_get_id (package));
}
static gchar **
pk_console_resolve_packages (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
guint i;
guint len;
gchar *package_id;
GError *error_local = NULL;
g_autoptr(GPtrArray) array = NULL;
/* get length */
len = g_strv_length (packages);
g_debug ("resolving %i packages", len);
/* resolve each package */
array = g_ptr_array_new ();
for (i = 0; i < len; i++) {
package_id = pk_console_resolve_package (ctx,
packages[i],
&error_local);
if (package_id == NULL) {
if (g_error_matches (error_local,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_PACKAGE_NOT_FOUND)) {
/* TRANSLATORS: we asked to install a package
* that could not be found in any repo */
g_print ("%s: %s\n", _("Package not found"),
packages[i]);
g_clear_error (&error_local);
continue;
} else {
g_propagate_error (error, error_local);
return NULL;
}
}
g_ptr_array_add (array, package_id);
}
/* nothing */
if (array->len == 0) {
g_set_error_literal (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
/* TRANSLATORS: we couldn't find anything */
_("No packages were found"));
return NULL;
}
/* convert to GStrv */
g_ptr_array_add (array, NULL);
return g_strdupv ((gchar **) array->pdata);
}
static gboolean
pk_console_install_packages (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
gboolean reinstall_allowed = FALSE;
/* test to see if we've been given files, not packages */
for (guint i = 0; packages[i] != NULL; i++) {
if (g_file_test (packages[i], G_FILE_TEST_EXISTS)) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user used
* 'pkcon install dave.rpm' rather than
* 'pkcon install-local dave.rpm' */
_("Expected package name, actually got file. "
"Try using 'pkcon install-local %s' instead."),
packages[i]);
return FALSE;
}
}
reinstall_allowed = pk_task_get_allow_reinstall (PK_TASK (ctx->task));
/* assume arch filter unless specified otherwise */
if (!pk_bitfield_contain (ctx->filters, PK_FILTER_ENUM_ARCH) &&
!pk_bitfield_contain (ctx->filters, PK_FILTER_ENUM_NOT_ARCH))
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_ARCH);
/* assume non-source packages unless specified */
if (!pk_bitfield_contain (ctx->filters, PK_FILTER_ENUM_SOURCE) &&
!pk_bitfield_contain (ctx->filters, PK_FILTER_ENUM_NOT_SOURCE))
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NOT_SOURCE);
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NEWEST);
if (!reinstall_allowed)
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NOT_INSTALLED);
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
/* the the error was not "no package found", or we did allow reinstallations
* (and therefore didn't filter out already installed packages) we show the
* emitted error immediately. */
if (!g_error_matches (error_local, PK_CONSOLE_ERROR, PK_ERROR_ENUM_PACKAGE_NOT_FOUND) ||
reinstall_allowed) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error finding a package
* for installation. The detailed error follows. */
_("This tool could not find any available package: %s"),
error_local->message);
ctx->retval = PK_EXIT_CODE_FILE_NOT_FOUND;
return FALSE;
}
/* If we are here, the package may exist, but may already be installed.
* Check for that to provide a better error */
pk_bitfield_remove (ctx->filters, PK_FILTER_ENUM_NOT_INSTALLED);
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_INSTALLED);
package_ids = pk_console_resolve_packages (ctx, packages, NULL);
if (package_ids == NULL) {
/* the package does not exist at all */
g_set_error_literal (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: We were unable to find a package for installation. */
_("This tool could not find any available package."));
ctx->retval = PK_EXIT_CODE_FILE_NOT_FOUND;
} else {
/* the package exists, but is already installed */
g_set_error_literal (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error finding a package
* for installation, it may already be installed. */
_("The selected packages may already be installed."));
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
}
return FALSE;
}
/* do the async action */
pk_task_install_packages_async (PK_TASK (ctx->task),
package_ids, ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_remove_packages (PkConsoleCtx *ctx, gchar **packages, gboolean autoremove, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_INSTALLED);
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error getting the list
* of files for the package. The detailed error follows */
_("This tool could not find the installed package: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_remove_packages_async (PK_TASK (ctx->task),
package_ids,
TRUE, autoremove,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_download_packages (PkConsoleCtx *ctx, gchar **packages, const gchar *directory, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NOT_INSTALLED);
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error getting the list
* of files for the package. The detailed error follows */
_("This tool could not find the package: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_download_packages_async (PK_TASK (ctx->task),
package_ids,
directory,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_update_packages (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NOT_INSTALLED);
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NOT_SOURCE);
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NEWEST);
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error getting the list
* of files for the package. The detailed error follows */
_("This tool could not find the package: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_update_packages_async (PK_TASK (ctx->task),
package_ids,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_update_system_filter_helper (PkPackage *package, gpointer user_data)
{
PkInfoEnum package_enum = pk_package_get_info (package);
return (package_enum != PK_INFO_ENUM_OBSOLETING && package_enum != PK_INFO_ENUM_REMOVING);
}
static gboolean
pk_console_update_system (PkConsoleCtx *ctx, GError **error)
{
g_autoptr(PkPackageSack) sack = NULL;
g_autoptr(PkResults) results = NULL;
g_auto(GStrv) package_ids = NULL;
/* get the current updates */
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NEWEST);
results = pk_task_get_updates_sync (PK_TASK (ctx->task),
ctx->filters,
ctx->cancellable,
pk_console_progress_cb, ctx,
error);
if (results == NULL)
return FALSE;
/* do the async action */
sack = pk_results_get_package_sack (results);
pk_package_sack_remove_by_filter (sack, &pk_console_update_system_filter_helper, NULL);
package_ids = pk_package_sack_get_ids (sack);
if (g_strv_length (package_ids) == 0) {
pk_progress_bar_end (ctx->progressbar);
/* TRANSLATORS: there are no updates, so nothing to do */
g_print ("%s\n", _("No packages require updating to newer versions."));
ctx->retval = PK_EXIT_CODE_NOTHING_USEFUL;
return FALSE;
}
pk_task_update_packages_async (PK_TASK (ctx->task),
package_ids,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_upgrade_system (PkConsoleCtx *ctx, const gchar *distro_id, const gchar *upgrade_kind, GError **error)
{
pk_task_upgrade_system_async (PK_TASK (ctx->task),
distro_id,
pk_upgrade_kind_enum_from_string (upgrade_kind),
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_required_by (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_INSTALLED);
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error getting the list
* of files for the package. The detailed error follows */
_("This tool could not find all the packages: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_required_by_async (PK_TASK (ctx->task),
ctx->filters,
package_ids,
TRUE,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_depends_on (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error getting the
* dependencies for the package. The detailed error follows */
_("This tool could not find all the packages: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_depends_on_async (PK_TASK (ctx->task),
ctx->filters,
package_ids,
FALSE,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_get_details (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
/* local file */
if (g_file_test (packages[0], G_FILE_TEST_EXISTS)) {
pk_client_get_details_local_async (PK_CLIENT (ctx->task),
packages,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error getting the
* details about the package. The detailed error follows */
_("This tool could not find all the packages: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_get_details_async (PK_TASK (ctx->task),
package_ids,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_get_details_local (PkConsoleCtx *ctx, gchar **files, GError **error)
{
pk_client_get_details_local_async (PK_CLIENT (ctx->task),
files,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_get_files_local (PkConsoleCtx *ctx, gchar **files, GError **error)
{
pk_client_get_files_local_async (PK_CLIENT (ctx->task),
files,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_get_files (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
/* local file */
if (g_file_test (packages[0], G_FILE_TEST_EXISTS)) {
pk_client_get_files_local_async (PK_CLIENT (ctx->task),
packages,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The package name was not found in
* any software repositories. The detailed error follows */
_("This tool could not find all the packages: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_get_files_async (PK_TASK (ctx->task),
package_ids,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static gboolean
pk_console_get_update_detail (PkConsoleCtx *ctx, gchar **packages, GError **error)
{
g_autoptr(GError) error_local = NULL;
g_auto(GStrv) package_ids = NULL;
pk_bitfield_add (ctx->filters, PK_FILTER_ENUM_NOT_INSTALLED);
package_ids = pk_console_resolve_packages (ctx, packages, &error_local);
if (package_ids == NULL) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The package name was not found in
* any software repositories. The detailed error follows */
_("This tool could not find all the packages: %s"),
error_local->message);
return FALSE;
}
/* do the async action */
pk_task_get_update_detail_async (PK_TASK (ctx->task),
package_ids,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
return TRUE;
}
static void
pk_console_notify_connected_cb (PkControl *control_, GParamSpec *pspec, gpointer data)
{
PkConsoleCtx *ctx = (PkConsoleCtx *) data;
gboolean connected;
/* if the daemon crashed, don't hang around */
g_object_get (control_,
"connected", &connected,
NULL);
if (!connected) {
/* TRANSLATORS: This is when the daemon crashed, and we are up
* shit creek without a paddle */
g_print ("%s\n", _("The daemon crashed mid-transaction!"));
g_main_loop_quit (ctx->loop);
}
}
static gboolean
pk_console_sigint_cb (gpointer user_data)
{
PkConsoleCtx *ctx = (PkConsoleCtx *) user_data;
g_debug ("Handling SIGINT");
g_cancellable_cancel (ctx->cancellable);
return FALSE;
}
static gchar *
pk_console_get_summary (PkConsoleCtx *ctx)
{
GString *string;
string = g_string_new ("");
/* TRANSLATORS: This is the header to the --help menu */
g_string_append_printf (string, "%s\n\n%s\n", _("PackageKit Console Interface"),
/* these are commands we can use with pkcon */
_("Subcommands:"));
/* always */
g_string_append_printf (string, " %s\n", "backend-details");
g_string_append_printf (string, " %s\n", "get-roles");
g_string_append_printf (string, " %s\n", "get-groups");
g_string_append_printf (string, " %s\n", "get-filters");
g_string_append_printf (string, " %s\n", "get-transactions");
g_string_append_printf (string, " %s\n", "get-time");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_SEARCH_NAME) ||
pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_SEARCH_DETAILS) ||
pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_SEARCH_GROUP) ||
pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_SEARCH_FILE))
g_string_append_printf (string, " %s\n", "search [name|details|group|file] [data]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_INSTALL_PACKAGES))
g_string_append_printf (string, " %s\n", "install [packages]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_INSTALL_FILES))
g_string_append_printf (string, " %s\n", "install-local [files]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_DOWNLOAD_PACKAGES))
g_string_append_printf (string, " %s\n", "download [directory] [packages]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_INSTALL_SIGNATURE))
g_string_append_printf (string, " %s\n", "install-sig [type] [key_id] [package_id]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_REMOVE_PACKAGES))
g_string_append_printf (string, " %s\n", "remove [package]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_UPDATE_PACKAGES))
g_string_append_printf (string, " %s\n", "update <package>");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_REFRESH_CACHE))
g_string_append_printf (string, " %s\n", "refresh [force]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_RESOLVE))
g_string_append_printf (string, " %s\n", "resolve [package]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_UPDATES))
g_string_append_printf (string, " %s\n", "get-updates");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_DEPENDS_ON))
g_string_append_printf (string, " %s\n", "depends-on [package]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_REQUIRED_BY))
g_string_append_printf (string, " %s\n", "required-by [package]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_DETAILS))
g_string_append_printf (string, " %s\n", "get-details [package]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_DISTRO_UPGRADES))
g_string_append_printf (string, " %s\n", "get-distro-upgrades");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_FILES))
g_string_append_printf (string, " %s\n", "get-files [package]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_UPDATE_DETAIL))
g_string_append_printf (string, " %s\n", "get-update-detail [package]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_PACKAGES))
g_string_append_printf (string, " %s\n", "get-packages");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_REPO_LIST))
g_string_append_printf (string, " %s\n", "repo-list");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_REPO_ENABLE)) {
g_string_append_printf (string, " %s\n", "repo-enable [repo_id]");
g_string_append_printf (string, " %s\n", "repo-disable [repo_id]");
}
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_REPO_SET_DATA))
g_string_append_printf (string, " %s\n", "repo-set-data [repo_id] [parameter] [value]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_REPO_REMOVE))
g_string_append_printf (string, " %s\n", "repo-remove [repo_id] [autoremove]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_WHAT_PROVIDES))
g_string_append_printf (string, " %s\n", "what-provides [search]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_ACCEPT_EULA))
g_string_append_printf (string, " %s\n", "accept-eula [eula-id]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_GET_CATEGORIES))
g_string_append_printf (string, " %s\n", "get-categories");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_UPGRADE_SYSTEM))
g_string_append_printf (string, " %s\n", "upgrade-system [distro-name] [minimal|default|complete]");
if (pk_bitfield_contain (ctx->roles, PK_ROLE_ENUM_REPAIR_SYSTEM))
g_string_append_printf (string, " %s\n", "repair");
g_string_append_printf (string, " %s\n", "offline-get-prepared");
g_string_append_printf (string, " %s\n", "offline-trigger");
g_string_append_printf (string, " %s\n", "offline-cancel");
g_string_append_printf (string, " %s\n", "offline-status");
g_string_append_printf (string, " %s\n", "quit");
return g_string_free (string, FALSE);
}
static void
pk_console_get_time_since_action_cb (GObject *object, GAsyncResult *res, gpointer data)
{
guint time_ms;
PkConsoleCtx *ctx = (PkConsoleCtx *) data;
g_autoptr(GError) error = NULL;
/* get the results */
time_ms = pk_control_get_time_since_action_finish (ctx->control, res, &error);
if (time_ms == 0) {
/* TRANSLATORS: we keep a database updated with the time that an
* action was last executed */
g_print ("%s: %s\n", _("Failed to get the time since this action was last completed"), error->message);
goto out;
}
/* TRANSLATORS: this is the time since this role was used */
g_print ("%s: %is\n", _("Time since"), time_ms);
out:
g_main_loop_quit (ctx->loop);
}
static gboolean
pk_console_offline_get_prepared (GError **error)
{
guint i;
g_auto(GStrv) package_ids = NULL;
/* get data */
package_ids = pk_offline_get_prepared_ids (error);
if (package_ids == NULL) {
(*error)->code = PK_EXIT_CODE_FILE_NOT_FOUND;
return FALSE;
}
/* TRANSLATORS: There follows a list of packages downloaded and ready
* to be updated */
g_print ("%s\n", _("Prepared updates:"));
for (i = 0; package_ids[i] != NULL; i++) {
g_autofree gchar *tmp = NULL;
tmp = pk_package_id_to_printable (package_ids[i]);
g_print ("%s\n", tmp);
}
return TRUE;
}
static gboolean
pk_console_offline_status (GError **error)
{
g_autoptr(PkResults) results = NULL;
g_autoptr(PkError) error_code = NULL;
results = pk_offline_get_results (error);
if (results == NULL)
return FALSE;
error_code = pk_results_get_error_code (results);
if (error_code != NULL) {
g_print ("Status:\tFailed\n");
g_print ("ErrorCode:\%s\n", pk_error_enum_to_string (pk_error_get_code (error_code)));
g_print ("ErrorDetails:\%s\n", pk_error_get_details (error_code));
} else {
guint i;
g_autoptr(GPtrArray) array = NULL;
g_print ("Status:\tSuccess\n");
array = pk_results_get_package_array (results);
for (i = 0; i < array->len; i++) {
PkPackage *pkg;
g_autofree gchar *tmp = NULL;
pkg = g_ptr_array_index (array, i);
tmp = pk_package_id_to_printable (pk_package_get_id (pkg));
g_print ("Updated %s\n", tmp);
}
}
return TRUE;
}
static gboolean
pk_console_set_proxy (PkConsoleCtx *ctx, GError **error)
{
const gchar *ftp_proxy;
const gchar *http_proxy;
gboolean ret = TRUE;
g_autoptr(GError) error_local = NULL;
/* is anything set */
http_proxy = g_getenv ("http_proxy");
ftp_proxy = g_getenv ("ftp_proxy");
if (http_proxy == NULL && ftp_proxy == NULL)
return TRUE;
/* set all parameters */
ret = pk_control_set_proxy2 (ctx->control,
http_proxy,
g_getenv ("https_proxy"),
ftp_proxy,
g_getenv ("all_proxy"),
g_getenv ("no_proxy"),
g_getenv ("pac"),
ctx->cancellable,
&error_local);
if (!ret) {
g_set_error (error,
PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s: %s",
/* TRANSLATORS: The network settings could not be sent */
_("The proxy could not be set"),
error_local->message);
return FALSE;
}
return TRUE;
}
int
main (int argc, char *argv[])
{
PkConsoleCtx *ctx = NULL;
gboolean ret;
gboolean background = FALSE;
gboolean noninteractive = FALSE;
gboolean only_download = FALSE;
gboolean allow_downgrade = FALSE;
gboolean allow_reinstall = FALSE;
gboolean autoremove = FALSE;
guint cache_age = G_MAXUINT;
gint retval_copy = 0;
gboolean plain = FALSE;
gboolean allow_untrusted = FALSE;
gboolean program_version = FALSE;
gboolean run_mainloop = TRUE;
GOptionContext *context;
const gchar *mode;
const gchar *value = NULL;
const gchar *details = NULL;
const gchar *parameter = NULL;
PkBitfield groups;
gchar *text;
g_autoptr(GError) error = NULL;
g_autofree gchar *filter = NULL;
g_autofree gchar *options_help = NULL;
g_autofree gchar *summary = NULL;
guint bar_padding = 30;
guint bar_size = 25;
struct winsize w;
const GOptionEntry options[] = {
{ "version", '\0', 0, G_OPTION_ARG_NONE, &program_version,
/* TRANSLATORS: command line argument, just show the version string */
_("Show the program version and exit"), NULL},
{ "filter", '\0', 0, G_OPTION_ARG_STRING, &filter,
/* TRANSLATORS: command line argument, use a filter to narrow down results */
_("Set the filter, e.g. installed"), NULL},
{ "noninteractive", 'y', 0, G_OPTION_ARG_NONE, &noninteractive,
/* command line argument, do we ask questions */
_("Install the packages without asking for confirmation"), NULL },
{ "only-download", 'd', 0, G_OPTION_ARG_NONE, &only_download,
/* command line argument, do we just download or apply changes */
_("Prepare the transaction by downloading packages only"), NULL },
{ "allow-downgrade", 0, 0, G_OPTION_ARG_NONE, &allow_downgrade,
/* command line argument, do we allow package downgrades */
_("Allow packages to be downgraded during transaction"), NULL},
{ "allow-reinstall", 0, 0, G_OPTION_ARG_NONE, &allow_reinstall,
_("Allow packages to be reinstalled during transaction"), NULL},
{ "autoremove", 0, 0, G_OPTION_ARG_NONE, &autoremove,
_("Automatically remove unused dependencies"), NULL},
{ "background", 'n', 0, G_OPTION_ARG_NONE, &background,
/* TRANSLATORS: command line argument, this command is not a priority */
_("Run the command using idle network bandwidth and also using less power"), NULL},
{ "plain", 'p', 0, G_OPTION_ARG_NONE, &plain,
/* TRANSLATORS: command line argument, just output without fancy formatting */
_("Print to screen a machine readable output, rather than using animated widgets"), NULL},
{ "cache-age", 'c', 0, G_OPTION_ARG_INT, &cache_age,
/* TRANSLATORS: command line argument, just output without fancy formatting */
_("The maximum metadata cache age. Use -1 for 'never'."), NULL},
{ "allow-untrusted", '\0', 0, G_OPTION_ARG_NONE, &allow_untrusted,
/* command line argument, do we ask questions */
_("Allow untrusted packages to be installed."), NULL },
{ NULL}
};
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
/* do stuff on ctrl-c */
ctx = g_new0 (PkConsoleCtx, 1);
ctx->defered_status = PK_STATUS_ENUM_UNKNOWN;
ctx->loop = g_main_loop_new (NULL, FALSE);
g_unix_signal_add_full (G_PRIORITY_DEFAULT,
SIGINT,
pk_console_sigint_cb,
ctx,
NULL);
/* Shrink the progresbar to fit in small spaces i.e. termux, small tmux panes, large font terminals */
/* If ioctl reports back and the terminal is small, shrink to fit as best we can */
if (!ioctl (STDOUT_FILENO, TIOCGWINSZ, &w)) {
bar_padding = MAX (1, MIN ( (w.ws_col / 2), bar_padding));
bar_size = MAX (0, MIN (w.ws_col - (bar_padding + 11), bar_size));
}
ctx->progressbar = pk_progress_bar_new ();
pk_progress_bar_set_size (ctx->progressbar, bar_size);
pk_progress_bar_set_padding (ctx->progressbar, bar_padding);
ctx->cancellable = g_cancellable_new ();
context = g_option_context_new ("PackageKit Console Program");
g_option_context_set_summary (context, summary) ;
g_option_context_add_main_entries (context, options, NULL);
g_option_context_add_group (context, pk_debug_get_option_group ());
ret = g_option_context_parse (context, &argc, &argv, &error);
if (!ret) {
/* TRANSLATORS: we failed to contact the daemon */
g_print ("%s: %s\n", _("Failed to parse command line"), error->message);
retval_copy = PK_EXIT_CODE_SYNTAX_INVALID;
goto out_last;
}
/* we need the ctx->roles early, as we only show the user only what they can do */
ctx->control = pk_control_new ();
ret = pk_control_get_properties (ctx->control, ctx->cancellable, &error);
if (!ret) {
/* TRANSLATORS: we failed to contact the daemon */
g_print ("%s: %s\n", _("Failed to contact PackageKit"), error->message);
ctx->retval = PK_EXIT_CODE_CANNOT_SETUP;
goto out_last;
}
/* get data */
g_object_get (ctx->control,
"roles", &ctx->roles,
NULL);
/* set the summary text based on the available ctx->roles */
summary = pk_console_get_summary (ctx);
g_option_context_set_summary (context, summary) ;
options_help = g_option_context_get_help (context, TRUE, NULL);
/* check if we are on console */
if (!plain && isatty (fileno (stdout)) == 1)
ctx->is_console = TRUE;
if (program_version) {
g_print (VERSION "\n");
goto out;
}
if (argc < 2) {
g_print ("%s", options_help);
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
/* watch when the daemon aborts */
g_signal_connect (ctx->control, "notify::connected",
G_CALLBACK (pk_console_notify_connected_cb), ctx);
/* create transactions */
ctx->task = pk_task_text_new ();
g_object_set (ctx->task,
"background", background,
"simulate", !noninteractive && !only_download,
"interactive", !noninteractive,
"only-download", only_download,
"allow-downgrade", allow_downgrade,
"allow-reinstall", allow_reinstall,
"cache-age", cache_age,
"only-trusted", !allow_untrusted,
NULL);
/* set the proxy */
ret = pk_console_set_proxy (ctx, &error);
if (!ret) {
ctx->retval = PK_EXIT_CODE_CANNOT_SETUP;
goto out;
}
/* check filter */
if (filter != NULL) {
ctx->filters = pk_filter_bitfield_from_string (filter);
if (ctx->filters == 0) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s: %s",
/* TRANSLATORS: The user specified
* an incorrect filter */
_("The filter specified was invalid"),
filter);
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
}
g_debug ("filter=%s, filters=%" PK_BITFIELD_FORMAT, filter, ctx->filters);
mode = argv[1];
if (argc > 2)
value = argv[2];
if (argc > 3)
details = argv[3];
if (argc > 4)
parameter = argv[4];
/* start polkit tty agent to listen for password requests */
pk_polkit_agent_open ();
/* parse the big list */
if (strcmp (mode, "search") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: a search type can
* be name, details, file, etc */
"%s", _("A search type is required, e.g. name"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
} else if (strcmp (value, "name") == 0) {
if (details == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user
* needs to provide a search term */
"%s", _("A search term is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_search_names_async (PK_TASK (ctx->task),
ctx->filters,
argv + 3,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (value, "details") == 0) {
if (details == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user needs
* to provide a search term */
"%s", _("A search term is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_search_details_async (PK_TASK (ctx->task),
ctx->filters,
argv + 3,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (value, "group") == 0) {
if (details == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user needs
* to provide a search term */
"%s", _("A search term is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_search_groups_async (PK_TASK (ctx->task),
ctx->filters,
argv + 3,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (value, "file") == 0) {
if (details == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user needs
* to provide a search term */
"%s", _("A search term is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_search_files_async (PK_TASK (ctx->task),
ctx->filters,
argv + 3,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else {
/* fallback to a generic search */
pk_task_search_details_async (PK_TASK (ctx->task),
ctx->filters,
argv + 2,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
}
} else if (strcmp (mode, "install") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user did not
* specify what they wanted to install */
"%s", _("A package name to install is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_install_packages (ctx,
argv + 2,
&error);
} else if (strcmp (mode, "install-local") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user did not
* specify what they wanted to install */
"%s", _("A filename to install is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_install_files_async (PK_TASK (ctx->task),
argv + 2,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "install-sig") == 0) {
if (value == NULL || details == NULL || parameter == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: geeky error, real
* users won't see this */
"%s", _("A type, key_id and package_id are required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_client_install_signature_async (PK_CLIENT (ctx->task),
PK_SIGTYPE_ENUM_GPG,
details,
parameter,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "remove") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user did not
* specify what they wanted to remove */
"%s", _("A package name to remove is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_remove_packages (ctx, argv + 2, autoremove, &error);
} else if (strcmp (mode, "download") == 0) {
if (value == NULL || details == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the user did not
* specify anything about what to
* download or where */
"%s", _("A destination directory and the package names to download are required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
ret = g_file_test (value, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
if (!ret) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: the directory does
* not exist, so we can't continue */
"%s: %s", _("Directory not found"), value);
ctx->retval = PK_EXIT_CODE_FILE_NOT_FOUND;
goto out;
}
run_mainloop = pk_console_download_packages (ctx,
argv + 3,
value,
&error);
} else if (strcmp (mode, "accept-eula") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: geeky error, real
* users won't see this */
"%s", _("A licence identifier (eula-id) is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_client_accept_eula_async (PK_CLIENT (ctx->task),
value,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "update") == 0) {
if (value == NULL) {
/* do the system update */
run_mainloop = pk_console_update_system (ctx, &error);
} else {
run_mainloop = pk_console_update_packages (ctx,
argv + 2,
&error);
}
} else if (strcmp (mode, "resolve") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user did not
* specify a package name */
"%s", _("A package name to resolve is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_resolve_async (PK_TASK (ctx->task),
ctx->filters,
argv + 2,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "repo-enable") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user did not
* specify a repository name */
"%s", _("A repository name is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_repo_enable_async (PK_TASK (ctx->task),
value,
TRUE,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "repo-disable") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user did not
* specify a repository name */
"%s", _("A repository name is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_repo_enable_async (PK_TASK (ctx->task),
value,
FALSE,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "repo-set-data") == 0) {
if (value == NULL || details == NULL || parameter == NULL) {
/* TRANSLATORS: The user didn't provide any data */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A repo name, parameter and value are required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_client_repo_set_data_async (PK_CLIENT (ctx->task),
value,
details,
parameter,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "repo-remove") == 0) {
if (value == NULL || details == NULL) {
/* TRANSLATORS: The user didn't provide any data */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A repo id and autoremove required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_client_repo_remove_async (PK_CLIENT (ctx->task),
pk_bitfield_from_enums (PK_TRANSACTION_FLAG_ENUM_SIMULATE,
-1),
value,
atoi (details),
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "repo-list") == 0) {
pk_task_get_repo_list_async (PK_TASK (ctx->task),
ctx->filters,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "get-time") == 0) {
PkRoleEnum role;
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user didn't
* specify what action to use */
"%s", _("An action, e.g. 'update-packages' is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
role = pk_role_enum_from_string (value);
if (role == PK_ROLE_ENUM_UNKNOWN) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user specified
* an invalid action */
"%s", _("A correct role is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_control_get_time_since_action_async (ctx->control,
role,
ctx->cancellable,
pk_console_get_time_since_action_cb, ctx);
} else if (strcmp (mode, "quit") == 0) {
pk_control_suggest_daemon_quit (ctx->control,
ctx->cancellable,
NULL);
run_mainloop = FALSE;
} else if (strcmp (mode, "depends-on") == 0) {
if (value == NULL) {
/* TRANSLATORS: The user did not provide a package name */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A package name is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_depends_on (ctx, argv + 2, &error);
} else if (strcmp (mode, "get-distro-upgrades") == 0) {
pk_client_get_distro_upgrades_async (PK_CLIENT (ctx->task),
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "get-update-detail") == 0) {
if (value == NULL) {
/* TRANSLATORS: The user did not provide a package name */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A package name is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_get_update_detail (ctx, argv + 2, &error);
} else if (strcmp (mode, "required-by") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user did not
* provide a package name */
"%s", _("A package name is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_required_by (ctx, argv + 2, &error);
} else if (strcmp (mode, "what-provides") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: each package
* "provides" certain things, e.g.
* mime(gstreamer-decoder-mp3),
* the user didn't specify it */
"%s", _("A package provide string is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
pk_task_what_provides_async (PK_TASK (ctx->task),
ctx->filters,
argv + 2,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "get-details") == 0) {
if (value == NULL) {
/* TRANSLATORS: The user did not provide a package name */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A package name is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_get_details (ctx, argv + 2, &error);
} else if (strcmp (mode, "get-details-local") == 0) {
if (value == NULL) {
/* TRANSLATORS: The user did not provide a package name */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A filename is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_get_details_local (ctx, argv + 2, &error);
} else if (strcmp (mode, "get-files-local") == 0) {
if (value == NULL) {
/* TRANSLATORS: The user did not provide a package name */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A filename is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_get_files_local (ctx, argv + 2, &error);
} else if (strcmp (mode, "get-files") == 0) {
if (value == NULL) {
/* TRANSLATORS: The user did not provide a package name */
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
"%s", _("A package name is required"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
run_mainloop = pk_console_get_files (ctx, argv + 2, &error);
} else if (strcmp (mode, "get-updates") == 0) {
pk_task_get_updates_async (PK_TASK (ctx->task),
ctx->filters,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "get-categories") == 0) {
pk_task_get_categories_async (PK_TASK (ctx->task),
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "get-packages") == 0) {
pk_task_get_packages_async (PK_TASK (ctx->task),
ctx->filters,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "upgrade-system") == 0) {
/* do the system upgrade */
run_mainloop = pk_console_upgrade_system (ctx, value, details, &error);
} else if (strcmp (mode, "get-roles") == 0) {
text = pk_role_bitfield_to_string (ctx->roles);
g_strdelimit (text, ";", '\n');
g_print ("%s\n", text);
g_free (text);
run_mainloop = FALSE;
} else if (strcmp (mode, "get-filters") == 0) {
g_object_get (ctx->control,
"filters", &ctx->filters,
NULL);
text = pk_filter_bitfield_to_string (ctx->filters);
g_strdelimit (text, ";", '\n');
g_print ("%s\n", text);
g_free (text);
run_mainloop = FALSE;
} else if (strcmp (mode, "backend-details") == 0) {
gchar *backend_author = NULL;
gchar *backend_description = NULL;
gchar *backend_name = NULL;
g_object_get (ctx->control,
"backend-author", &backend_author,
"backend-description", &backend_description,
"backend-name", &backend_name,
NULL);
if (backend_name != NULL && backend_name[0] != '\0') {
/* TRANSLATORS: this is the name of the backend */
g_print ("%s:\t\t%s\n", _("Name"), backend_name);
}
if (backend_description != NULL && backend_description[0] != '\0') {
/* TRANSLATORS: this is the description of the backend */
g_print ("%s:\t%s\n", _("Description"), backend_description);
}
if (backend_author != NULL && backend_author[0] != '\0') {
/* TRANSLATORS: this is the author of the backend */
g_print ("%s:\t%s\n", _("Author"), backend_author);
}
g_free (backend_name);
g_free (backend_description);
g_free (backend_author);
run_mainloop = FALSE;
} else if (strcmp (mode, "get-groups") == 0) {
g_object_get (ctx->control,
"groups", &groups,
NULL);
text = pk_group_bitfield_to_string (groups);
g_strdelimit (text, ";", '\n');
g_print ("%s\n", text);
g_free (text);
run_mainloop = FALSE;
} else if (strcmp (mode, "offline-get-prepared") == 0) {
run_mainloop = FALSE;
ret = pk_console_offline_get_prepared (&error);
if (!ret)
ctx->retval = error->code;
} else if (strcmp (mode, "offline-trigger") == 0) {
run_mainloop = FALSE;
ret = pk_offline_trigger_with_flags (PK_OFFLINE_ACTION_REBOOT, PK_OFFLINE_FLAGS_INTERACTIVE, NULL, &error);
if (!ret)
ctx->retval = error->code;
} else if (strcmp (mode, "offline-cancel") == 0) {
run_mainloop = FALSE;
ret = pk_offline_cancel_with_flags (PK_OFFLINE_FLAGS_INTERACTIVE, NULL, &error);
if (!ret)
ctx->retval = error->code;
} else if (strcmp (mode, "offline-status") == 0) {
run_mainloop = FALSE;
ret = pk_console_offline_status (&error);
if (!ret)
ctx->retval = error->code;
} else if (strcmp (mode, "get-transactions") == 0) {
pk_client_get_old_transactions_async (PK_CLIENT (ctx->task),
10,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "refresh") == 0) {
gboolean force = (value != NULL && g_strcmp0 (value, "force") == 0);
pk_task_refresh_cache_async (PK_TASK (ctx->task),
force,
ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "repair") == 0) {
pk_task_repair_system_async (PK_TASK (ctx->task), ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else if (strcmp (mode, "list-create") == 0) {
if (value == NULL) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user did not provide a distro name */
"%s", _("You need to specify a list file to create"));
ctx->retval = PK_EXIT_CODE_SYNTAX_INVALID;
goto out;
}
/* file exists */
ret = g_file_test (value, G_FILE_TEST_EXISTS);
if (ret) {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: There was an error
* getting the list of packages.
* The filename follows */
_("File already exists: %s"), value);
ctx->retval = PK_EXIT_CODE_FILE_NOT_FOUND;
goto out;
}
/* get package list */
g_object_set_data_full (G_OBJECT (ctx->task),
"PkConsole:list-create-filename",
g_strdup (value),
g_free);
pk_task_get_packages_async (PK_TASK (ctx->task), ctx->filters, ctx->cancellable,
pk_console_progress_cb, ctx,
pk_console_finished_cb, ctx);
} else {
error = g_error_new (PK_CONSOLE_ERROR,
PK_ERROR_ENUM_INTERNAL_ERROR,
/* TRANSLATORS: The user tried to use an
* unsupported option on the command line */
_("Option '%s' is not supported"), mode);
}
/* do we wait for the method? */
if (run_mainloop && error == NULL)
g_main_loop_run (ctx->loop);
out:
if (error != NULL) {
/* TRANSLATORS: Generic failure of what they asked to do */
g_print ("%s: %s\n", _("Command failed"), error->message);
if (ctx->retval == EXIT_SUCCESS)
ctx->retval = EXIT_FAILURE;
}
/* stop listening for polkit questions */
pk_polkit_agent_close ();
if (ctx != NULL) {
retval_copy = ctx->retval;
g_object_unref (ctx->progressbar);
g_object_unref (ctx->control);
if (ctx->task != NULL)
g_object_unref (ctx->task);
g_object_unref (ctx->cancellable);
if (ctx->defered_status_id > 0)
g_source_remove (ctx->defered_status_id);
g_main_loop_unref (ctx->loop);
g_free (ctx);
}
out_last:
g_option_context_free (context);
return retval_copy;
}