2430 lines
77 KiB
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", ×pec,
|
|
"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;
|
|
}
|
|
|