Logo Search packages:      
Sourcecode: packagekit version File versions  Download package

pk-console.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2007 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <dbus/dbus-glib.h>

#include <pk-debug.h>
#include <pk-client.h>
#include <pk-package-id.h>
#include <pk-enum-list.h>
#include <pk-common.h>
#include <pk-connection.h>

#define PROGRESS_BAR_PADDING 22
#define MINIMUM_COLUMNS (PROGRESS_BAR_PADDING + 5)

static GMainLoop *loop = NULL;
static PkEnumList *role_list = NULL;
static gboolean is_console = FALSE;
static gboolean has_output = FALSE;
static gboolean printed_bar = FALSE;
static guint timer_id = 0;
static gchar *package_id = NULL;

typedef struct {
      gint position;
      gboolean move_forward;
} PulseState;

/**
 * pk_console_package_cb:
 **/
static void
pk_console_package_cb (PkClient *client, PkInfoEnum info, const gchar *package_id, const gchar *summary, gpointer data)
{
      PkPackageId *ident;
      PkPackageId *spacing;
      gchar *info_text;
      guint extra = 0;

      /* if on console, clear the progress bar line */
      if (is_console == TRUE && printed_bar == TRUE && has_output == FALSE) {
            g_print ("\r");
      }

      /* pass this out */
      info_text = pk_strpad (pk_info_enum_to_text (info), 12);

      spacing = pk_package_id_new ();
      ident = pk_package_id_new_from_string (package_id);

      /* these numbers are guesses */
      extra = 0;
      spacing->name = pk_strpad_extra (ident->name, 20, &extra);
      spacing->arch = pk_strpad_extra (ident->arch, 7, &extra);
      spacing->version = pk_strpad_extra (ident->version, 15, &extra);
      spacing->data = pk_strpad_extra (ident->data, 12, &extra);

      /* pretty print */
      g_print ("%s %s %s %s %s %s\n", info_text, spacing->name,
             spacing->arch, spacing->version, spacing->data, summary);

      /* free all the data */
      g_free (info_text);
      pk_package_id_free (ident);
      pk_package_id_free (spacing);

      /* don't do the percentage bar from now on */
      has_output = TRUE;
}

/**
 * pk_console_transaction_cb:
 **/
static void
pk_console_transaction_cb (PkClient *client, const gchar *tid, const gchar *timespec,
                     gboolean succeeded, PkRoleEnum role, guint duration,
                     const gchar *data, gpointer user_data)
{
      const gchar *role_text;
      role_text = pk_role_enum_to_text (role);
      g_print ("Transaction  : %s\n", tid);
      g_print (" timespec    : %s\n", timespec);
      g_print (" succeeded   : %i\n", succeeded);
      g_print (" role        : %s\n", role_text);
      g_print (" duration    : %i (seconds)\n", duration);
      g_print (" data        : %s\n", data);
}

/**
 * pk_console_update_detail_cb:
 **/
static void
pk_console_update_detail_cb (PkClient *client, const gchar *package_id,
                       const gchar *updates, const gchar *obsoletes,
                       const gchar *vendor_url, const gchar *bugzilla_url,
                       const gchar *cve_url, PkRestartEnum restart,
                       const gchar *update_text, gpointer data)
{
      g_print ("Update detail\n");
      g_print ("  package:    '%s'\n", package_id);
      if (pk_strzero (updates) == FALSE) {
            g_print ("  updates:    '%s'\n", updates);
      }
      if (pk_strzero (obsoletes) == FALSE) {
            g_print ("  obsoletes:  '%s'\n", obsoletes);
      }
      if (pk_strzero (vendor_url) == FALSE) {
            g_print ("  vendor URL: '%s'\n", vendor_url);
      }
      if (pk_strzero (bugzilla_url) == FALSE) {
            g_print ("  bug URL:    '%s'\n", bugzilla_url);
      }
      if (pk_strzero (cve_url) == FALSE) {
            g_print ("  cve URL:    '%s'\n", cve_url);
      }
      if (restart != PK_RESTART_ENUM_NONE) {
            g_print ("  restart:    '%s'\n", pk_restart_enum_to_text (restart));
      }
      if (pk_strzero (update_text) == FALSE) {
            g_print ("  update_text:'%s'\n", update_text);
      }
}

/**
 * pk_console_repo_detail_cb:
 **/
static void
pk_console_repo_detail_cb (PkClient *client, const gchar *repo_id,
                     const gchar *description, gboolean enabled, gpointer data)
{
      gchar *repo;
      repo = pk_strpad (repo_id, 28);
      if (enabled == TRUE) {
            g_print ("  enabled   %s %s\n", repo, description);
      } else {
            g_print ("  disabled  %s %s\n", repo, description);
      }
      g_free (repo);
}

/**
 * pk_console_get_terminal_columns:
 **/
static guint
pk_console_get_terminal_columns (void)
{
      struct winsize ws;

      ioctl (1, TIOCGWINSZ, &ws);
      if (ws.ws_col < MINIMUM_COLUMNS) {
            return MINIMUM_COLUMNS;
      }

      return ws.ws_col;
}

/**
 * pk_console_draw_progress_bar:
 **/
static void
pk_console_draw_progress_bar (guint percentage, guint remaining_time)
{
      guint i;
      guint progress_bar_size = pk_console_get_terminal_columns () - PROGRESS_BAR_PADDING;
      guint progress = (gint) (progress_bar_size * (gfloat) (percentage) / 100);
      guint remaining = progress_bar_size - progress;

      /* have we already been spinning? */
      if (timer_id != 0) {
            g_source_remove (timer_id);
            timer_id = 0;
      }

      /* we need to do an extra line */
      printed_bar = TRUE;

      g_print ("\r    [");
      for (i = 0; i < progress; i++) {
            g_print ("=");
      }
      for (i = 0; i < remaining; i++) {
            g_print (".");
      }
      g_print ("]  %3i%%", percentage);
      if (remaining_time != 0) {
            if (remaining_time > 60) {
                  guint remaining_minutes = remaining_time / 60;
                  if (remaining_minutes > 60) {
                        guint remaining_hours = remaining_time / 3600;
                        g_print (" (%2ih eta)", remaining_hours);
                  } else {
                        g_print (" (%2im eta)", remaining_minutes);
                  }
            } else {
                  g_print (" (%2is eta)", remaining_time);
            }
      } else {
            g_print ("          ");
      }
      if (percentage == 100) {
            g_print ("\n");
      }
}

/**
 * pk_console_pulse_bar:
 **/
static gboolean
pk_console_pulse_bar (PulseState *pulse_state)
{
      guint i;
      guint progress_bar_size = pk_console_get_terminal_columns () - PROGRESS_BAR_PADDING;
      gchar *padding;

      /* don't spin if we have had output */
      if (has_output == TRUE) {
            return FALSE;
      }

      /* we need to do an extra line */
      printed_bar = TRUE;

      /* the clever pulse code */
      printf("\r    [");
      for (i = 0; i < pulse_state->position - 1; i++) {
            g_print (".");
      }
      printf("===");
      for (i = pulse_state->position; i < progress_bar_size - 2; i++) {
            g_print (".");
      }
      g_print ("]");

      if (pulse_state->move_forward == TRUE) {
            if (pulse_state->position == progress_bar_size - 2) {
                  pulse_state->move_forward = FALSE;
                  pulse_state->position--;
            } else {
                  pulse_state->position++;
            }
      } else if (pulse_state->move_forward == FALSE) {
            if (pulse_state->position == 1) {
                  pulse_state->move_forward = TRUE;
                  pulse_state->position++;
            } else {
                  pulse_state->position--;
            }
      }

      /* Move the cursor off the screen. */
      padding = g_strnfill (PROGRESS_BAR_PADDING - 6, ' ');
      g_print ("%s", padding);
      g_free (padding);

      return TRUE;
}

/**
 * pk_console_draw_progress_bar:
 **/
static void
pk_console_draw_pulse_bar (void)
{
      static PulseState pulse_state;

      /* have we already got zero percent? */
      if (timer_id != 0) {
            return;
      }
      has_output = FALSE;
      if (is_console == TRUE) {
            pulse_state.position = 1;
            pulse_state.move_forward = TRUE;
            timer_id = g_timeout_add (40, (GSourceFunc) pk_console_pulse_bar, &pulse_state);
      }
}

/**
 * pk_console_progress_changed_cb:
 **/
static void
pk_console_progress_changed_cb (PkClient *client, guint percentage, guint subpercentage,
                        guint elapsed, guint remaining, gpointer data)
{
      if (is_console == TRUE) {
            if (percentage == PK_CLIENT_PERCENTAGE_INVALID) {
                  pk_console_draw_pulse_bar ();
            } else {
                  pk_console_draw_progress_bar (percentage, remaining);
            }
      } else {
            g_print ("%i%%\n", percentage);
      }
}

const gchar *summary =
      "PackageKit Console Interface\n"
      "\n"
      "Subcommands:\n"
      "  search name|details|group|file data\n"
      "  install <package_id>\n"
      "  install-file <file>\n"
      "  remove <package_id>\n"
      "  update <package_id>\n"
      "  refresh\n"
      "  resolve\n"
      "  force-refresh\n"
      "  update-system\n"
      "  get updates\n"
      "  get depends <package_id>\n"
      "  get requires <package_id>\n"
      "  get description <package_id>\n"
      "  get files <package_id>\n"
      "  get updatedetail <package_id>\n"
      "  get actions\n"
      "  get groups\n"
      "  get filters\n"
      "  get transactions\n"
      "  get repos\n"
      "  enable-repo <repo_id>\n"
      "  disable-repo <repo_id>\n"
      "  set-repo-data <repo_id> <parameter> <value>\n"
      "\n"
      "  package_id is typically gimp;2:2.4.0-0.rc1.1.fc8;i386;development";

/**
 * pk_client_wait:
 **/
static gboolean
pk_client_wait (void)
{
      pk_debug ("starting loop");
      g_main_loop_run (loop);
      return TRUE;
}

/**
 * pk_console_finished_cb:
 **/
static void
pk_console_finished_cb (PkClient *client, PkExitEnum exit, guint runtime, gpointer data)
{
      PkRoleEnum role;
      gchar *blanking;
      const gchar *role_text;
      gfloat time;
      PkRestartEnum restart;

      /* cancel the spinning */
      if (timer_id != 0) {
            g_source_remove (timer_id);
      }

      /* if on console, clear the progress bar line */
      if (is_console == TRUE && printed_bar == TRUE && has_output == FALSE) {
            g_print ("\r");
            blanking = g_strnfill (pk_console_get_terminal_columns (), ' ');
            g_print ("%s", blanking);
            g_free (blanking);
            g_print ("\r");
      }

      pk_client_get_role (client, &role, NULL);
      role_text = pk_role_enum_to_text (role);
      time = (gfloat) runtime / 1000.0;
      g_print ("%s runtime was %.1f seconds\n", role_text, time);

      /* is there any restart to notify the user? */
      restart = pk_client_get_require_restart (client);
      if (restart != PK_RESTART_ENUM_NONE) {
            g_print ("Requires restart: %s\n", pk_restart_enum_to_text (restart));
      }

      if (loop != NULL) {
            g_main_loop_quit (loop);
      }
}

/**
 * pk_console_perhaps_resolve:
 **/
static gchar *
pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar *package)
{
      gboolean ret;
      gboolean valid;
      PkClient *client_resolve;
      const gchar *filter_text;
      guint i;
      guint length;
      PkPackageItem *item;

      /* have we passed a complete package_id? */
      valid = pk_package_id_check (package);
      if (valid == TRUE) {
            return g_strdup (package);
      }

      /* we need to resolve it */
      client_resolve = pk_client_new ();
      g_signal_connect (client_resolve, "finished",
      /* TODO: send local loop */
                    G_CALLBACK (pk_console_finished_cb), NULL);
      filter_text = pk_filter_enum_to_text (filter);
      pk_client_set_use_buffer (client_resolve, TRUE);
      ret = pk_client_resolve (client_resolve, filter_text, package);
      if (ret == FALSE) {
            pk_warning ("Resolve is not supported in this backend");
            return NULL;
      } else {
            g_main_loop_run (loop);
      }

      /* get length of items found */
      length = pk_client_package_buffer_get_size (client_resolve);

      /* only found one, great! */
      if (length == 1) {
            item = pk_client_package_buffer_get_item (client_resolve, 0);
            return item->package_id;
      }

      /* else list the options if multiple matches found */
      if (length != 0) {
            g_print ("There are multiple matches\n");
            for (i=0; i<length; i++) {
                  item = pk_client_package_buffer_get_item (client_resolve, i);
                  g_print ("%i. %s\n", i+1, item->package_id);
            }
      }
      return NULL;
}

/**
 * pk_console_install_package:
 **/
static gboolean
pk_console_install_package (PkClient *client, const gchar *package)
{
      gboolean ret;
      gchar *package_id;
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to install\n");
            return FALSE;
      }
      ret = pk_client_install_package (client, package_id);
      g_free (package_id);
      return ret;
}

/**
 * pk_console_remove_only:
 **/
static gboolean
pk_console_remove_only (PkClient *client, gboolean force)
{
      gboolean ret;

      pk_debug ("remove %s", package_id);
      pk_client_reset (client);
      ret = pk_client_remove_package (client, package_id, force);
      /* ick, we failed so pretend we didn't do the action */
      if (ret == FALSE) {
            pk_warning ("The package could not be removed");
      }
      return ret;
}

/**
 * pk_console_requires_finished_cb:
 **/
static void
pk_console_requires_finished_cb (PkClient *client2, PkStatusEnum status, guint runtime, PkClient *client)
{
      guint length;
      PkPackageItem *item;
      PkPackageId *ident;
      guint i;
      gboolean remove;

      /* see how many packages there are */
      length = pk_client_package_buffer_get_size (client2);

      /* if there are no required packages, just do the remove */
      if (length == 0) {
            pk_debug ("no requires");
            pk_console_remove_only (client, FALSE);
            g_object_unref (client2);
            return;
      }

      /* present this to the user */
      g_print ("The following packages have to be removed:\n");
      for (i=0; i<length; i++) {
            item = pk_client_package_buffer_get_item (client2, i);
            ident = pk_package_id_new_from_string (item->package_id);
            g_print ("%i\t%s-%s\n", i, ident->name, ident->version);
            pk_package_id_free (ident);
      }

      /* check for user input */
      g_print ("Okay to remove additional packages? [N/y]\n");

      /* TODO: prompt the user */
      remove = FALSE;

      if (remove == FALSE) {
            g_print ("Cancelled!\n");
            if (loop != NULL) {
                  g_main_loop_quit (loop);
                  pk_debug ("<kjjjjjjjjjjjjjjjjjjjjjjjjjjjjj");
            }
      } else {
            pk_debug ("the user aggreed, remove with deps");
            pk_console_remove_only (client, TRUE);
      }
      g_object_unref (client2);
}

/**
 * pk_console_remove_package:
 **/
static gboolean
pk_console_remove_package (PkClient *client, const gchar *package)
{
      PkClient *client2;

      g_free (package_id);
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to remove\n");
            return FALSE;
      }

      /* are we dumb and can't check for requires? */
      if (pk_enum_list_contains (role_list, PK_ROLE_ENUM_GET_REQUIRES) == FALSE) {
            /* no, just try to remove it without deps */
            pk_console_remove_only (client, FALSE);
            return TRUE;
      }

      /* see if any packages require this one */
      client2 = pk_client_new ();
      pk_client_set_use_buffer (client2, TRUE);
      g_signal_connect (client2, "finished",
                    G_CALLBACK (pk_console_requires_finished_cb), client);
      pk_debug ("getting requires for %s", package_id);
      pk_client_get_requires (client2, package_id, TRUE);
      return TRUE;
}

/**
 * pk_console_update_package:
 **/
static gboolean
pk_console_update_package (PkClient *client, const gchar *package)
{
      gboolean ret;
      gchar *package_id;
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to update\n");
            return FALSE;
      }
      ret = pk_client_update_package (client, package_id);
      g_free (package_id);
      return ret;
}

/**
 * pk_console_get_requires:
 **/
static gboolean
pk_console_get_requires (PkClient *client, const gchar *package)
{
      gboolean ret;
      gchar *package_id;
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NONE, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to get requires\n");
            return FALSE;
      }
      ret = pk_client_get_requires (client, package_id, TRUE);
      g_free (package_id);
      return ret;
}

/**
 * pk_console_get_depends:
 **/
static gboolean
pk_console_get_depends (PkClient *client, const gchar *package)
{
      gboolean ret;
      gchar *package_id;
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NONE, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to get depends\n");
            return FALSE;
      }
      ret = pk_client_get_depends (client, package_id, FALSE);
      g_free (package_id);
      return ret;
}

/**
 * pk_console_get_description:
 **/
static gboolean
pk_console_get_description (PkClient *client, const gchar *package)
{
      gboolean ret;
      gchar *package_id;
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NONE, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to get description\n");
            return FALSE;
      }
      ret = pk_client_get_description (client, package_id);
      g_free (package_id);
      return ret;
}

/**
 * pk_console_get_files:
 **/
static gboolean
pk_console_get_files (PkClient *client, const gchar *package)
{
      gboolean ret;
      gchar *package_id;
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NONE, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to get files\n");
            return FALSE;
      }
      ret = pk_client_get_files (client, package_id);
      g_free (package_id);
      return ret;
}

/**
 * pk_console_get_update_detail
 **/
static gboolean
pk_console_get_update_detail(PkClient *client, const gchar *package)
{
      gboolean ret;
      gchar *package_id;
      package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, package);
      if (package_id == NULL) {
            g_print ("Could not find a package with that name to get update details\n");
            return FALSE;
      }
      ret = pk_client_get_update_detail (client, package_id);
      g_free (package_id);
      return ret;
}

/**
 * pk_console_process_commands:
 **/
static gboolean
pk_console_process_commands (PkClient *client, int argc, char *argv[], gboolean wait_override, GError **error)
{
      const gchar *mode;
      const gchar *value = NULL;
      const gchar *details = NULL;
      const gchar *parameter = NULL;
      gboolean wait = FALSE;
      PkEnumList *elist;

      mode = argv[1];
      if (argc > 2) {
            value = argv[2];
      }
      if (argc > 3) {
            details = argv[3];
      }
      if (argc > 4) {
            parameter = argv[4];
      }

      if (strcmp (mode, "search") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a search type");
                  return FALSE;
            } else if (strcmp (value, "name") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  } else {
                        wait = pk_client_search_name (client, "none", details);
                  }
            } else if (strcmp (value, "details") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  } else {
                        wait = pk_client_search_details (client, "none", details);
                  }
            } else if (strcmp (value, "group") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  } else {
                        wait = pk_client_search_group (client, "none", details);
                  }
            } else if (strcmp (value, "file") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  } else {
                        wait = pk_client_search_file (client, "none", details);
                  }
            } else {
                  g_set_error (error, 0, 0, "invalid search type");
            }
      } else if (strcmp (mode, "install") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a package to install");
                  return FALSE;
            } else {
                  wait = pk_console_install_package (client, value);
            }
      } else if (strcmp (mode, "install-file") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a package to install");
                  return FALSE;
            } else {
                  wait = pk_client_install_file (client, value);
            }
      } else if (strcmp (mode, "remove") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a package to remove");
                  return FALSE;
            } else {
                  wait = pk_console_remove_package (client, value);
            }
      } else if (strcmp (mode, "update") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a package to update");
                  return FALSE;
            } else {
                  wait = pk_console_update_package (client, value);
            }
      } else if (strcmp (mode, "resolve") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a package name to resolve");
                  return FALSE;
            } else {
                  wait = pk_client_resolve (client, "none", value);
            }
      } else if (strcmp (mode, "enable-repo") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a repo name");
                  return FALSE;
            } else {
                  pk_client_repo_enable (client, value, TRUE);
            }
      } else if (strcmp (mode, "disable-repo") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a repo name");
                  return FALSE;
            } else {
                  wait = pk_client_repo_enable (client, value, FALSE);
            }
      } else if (strcmp (mode, "set-repo-data") == 0) {
            if (value == NULL || details == NULL || parameter == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a repo name/parameter and value");
                  return FALSE;
            } else {
                  wait = pk_client_repo_set_data (client, value, details, parameter);
            }
      } else if (strcmp (mode, "get") == 0) {
            if (value == NULL) {
                  g_set_error (error, 0, 0, "you need to specify a get type");
                  return FALSE;
            } else if (strcmp (value, "time") == 0) {
                  PkRoleEnum role;
                  guint time;
                  gboolean ret;
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  }
                  role = pk_role_enum_from_text (details);
                  if (role == PK_ROLE_ENUM_UNKNOWN) {
                        g_set_error (error, 0, 0, "you need to specify a correct role");
                        return FALSE;
                  }
                  ret = pk_client_get_time_since_action (client, role, &time);
                  if (ret == FALSE) {
                        g_set_error (error, 0, 0, "failed to get last time");
                        return FALSE;
                  }
                  g_print ("time since %s is %is\n", details, time);
            } else if (strcmp (value, "depends") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  } else {
                        wait = pk_console_get_depends (client, details);
                  }
            } else if (strcmp (value, "updatedetail") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  } else {
                        wait = pk_console_get_update_detail (client, details);
                  }
            } else if (strcmp (value, "requires") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a search term");
                        return FALSE;
                  } else {
                        wait = pk_console_get_requires (client, details);
                  }
            } else if (strcmp (value, "description") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a package to find the description for");
                        return FALSE;
                  } else {
                        wait = pk_console_get_description (client, details);
                  }
            } else if (strcmp (value, "files") == 0) {
                  if (details == NULL) {
                        g_set_error (error, 0, 0, "you need to specify a package to find the files for");
                        return FALSE;
                  } else {
                        wait = pk_console_get_files (client, details);
                  }
            } else if (strcmp (value, "updates") == 0) {
                  wait = pk_client_get_updates (client);
            } else if (strcmp (value, "actions") == 0) {
                  elist = pk_client_get_actions (client);
                  pk_enum_list_print (elist);
                  g_object_unref (elist);
            } else if (strcmp (value, "filters") == 0) {
                  elist = pk_client_get_filters (client);
                  pk_enum_list_print (elist);
                  g_object_unref (elist);
            } else if (strcmp (value, "repos") == 0) {
                  wait = pk_client_get_repo_list (client);
            } else if (strcmp (value, "groups") == 0) {
                  elist = pk_client_get_groups (client);
                  pk_enum_list_print (elist);
                  g_object_unref (elist);
            } else if (strcmp (value, "transactions") == 0) {
                  wait = pk_client_get_old_transactions (client, 10);
            } else {
                  g_set_error (error, 0, 0, "invalid get type");
            }
      } else if (strcmp (mode, "update-system") == 0) {
            wait = pk_client_update_system (client);
      } else if (strcmp (mode, "refresh") == 0) {
            wait = pk_client_refresh_cache (client, FALSE);
      } else if (strcmp (mode, "force-refresh") == 0) {
            wait = pk_client_refresh_cache (client, TRUE);
      } else {
            g_set_error (error, 0, 0, "option not yet supported");
      }

      /* only wait if success */
      if (wait == TRUE && wait_override == TRUE) {
            pk_client_wait ();
      }
      return TRUE;
}

/**
 * pk_console_error_code_cb:
 **/
static void
pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gchar *details, gpointer data)
{
      /* if on console, clear the progress bar line */
      if (is_console == TRUE && printed_bar == TRUE) {
            g_print ("\n");
      }
      g_print ("Error: %s : %s\n", pk_error_enum_to_text (error_code), details);
}

/**
 * pk_console_description_cb:
 **/
static void
pk_console_description_cb (PkClient *client, const gchar *package_id,
                     const gchar *license, PkGroupEnum group,
                     const gchar *description, const gchar *url,
                     gulong size, gpointer data)
{
      /* if on console, clear the progress bar line */
      if (is_console == TRUE && printed_bar == TRUE) {
            g_print ("\n");
      }
      g_print ("Package description\n");
      g_print ("  package:     '%s'\n", package_id);
      g_print ("  license:     '%s'\n", license);
      g_print ("  group:       '%s'\n", pk_group_enum_to_text (group));
      g_print ("  description: '%s'\n", description);
      g_print ("  size:        '%ld' bytes\n", size);
      g_print ("  url:         '%s'\n", url);
}

/**
 * pk_console_files_cb:
 **/
static void
pk_console_files_cb (PkClient *client, const gchar *package_id,
                 const gchar *filelist, gpointer data)
{
      gchar **filevector = g_strsplit (filelist, ";", 0);

      /* if on console, clear the progress bar line */
      if (is_console == TRUE && printed_bar == TRUE) {
            g_print ("\n");
      }

      g_print ("Package files\n");

      if (*filevector != NULL) {
            gchar **current_file = filevector;

            while (*current_file != NULL) {
                  g_print ("  %s\n", *current_file);
                  current_file++;
            }
      } else {
          g_print ("  no files\n");
      }

      g_strfreev (filevector);
}

/**
 * pk_console_repo_signature_required_cb:
 **/
static void
pk_console_repo_signature_required_cb (PkClient *client, const gchar *repository_name, const gchar *key_url,
                               const gchar *key_userid, const gchar *key_id, const gchar *key_fingerprint,
                               const gchar *key_timestamp, PkSigTypeEnum type, gpointer data)
{
      g_print ("Signature Required\n");
      g_print ("  repo name:       '%s'\n", repository_name);
      g_print ("  key url:         '%s'\n", key_url);
      g_print ("  key userid:      '%s'\n", key_userid);
      g_print ("  key id:          '%s'\n", key_id);
      g_print ("  key fingerprint: '%s'\n", key_fingerprint);
      g_print ("  key timestamp:   '%s'\n", key_timestamp);
      g_print ("  key type:        '%s'\n", pk_sig_type_enum_to_text (type));

}

/**
 * pk_connection_changed_cb:
 **/
static void
pk_connection_changed_cb (PkConnection *pconnection, gboolean connected, gpointer data)
{
      /* if the daemon crashed, don't hang around */
      if (connected == FALSE && loop != NULL) {
            pk_warning ("The daemon went away...");
            g_main_loop_quit (loop);
      }
}

/**
 * main:
 **/
int
main (int argc, char *argv[])
{
      DBusGConnection *system_connection;
      GError *error = NULL;
      PkClient *client;
      PkConnection *pconnection;
      gboolean verbose = FALSE;
      gboolean program_version = FALSE;
      gboolean nowait = FALSE;
      GOptionContext *context;
      gchar *options_help;

      const GOptionEntry options[] = {
            { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
                  "Show extra debugging information", NULL },
            { "version", '\0', 0, G_OPTION_ARG_NONE, &program_version,
                  "Show the program version and exit", NULL},
            { "nowait", 'n', 0, G_OPTION_ARG_NONE, &nowait,
                  "Exit without waiting for actions to complete", NULL},
            { NULL}
      };

      if (! g_thread_supported ()) {
            g_thread_init (NULL);
      }
      dbus_g_thread_init ();
      g_type_init ();

      /* check if we are on console */
      if (isatty (fileno (stdout)) == 1) {
            is_console = TRUE;
      }

      /* check dbus connections, exit if not valid */
      system_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
      if (error) {
            pk_warning ("%s", error->message);
            g_error_free (error);
            g_error ("This program cannot start until you start the dbus system service.");
      }

      context = g_option_context_new (_("SUBCOMMAND"));
      g_option_context_set_summary (context, summary) ;
      g_option_context_add_main_entries (context, options, NULL);
      g_option_context_parse (context, &argc, &argv, NULL);
      /* Save the usage string in case command parsing fails. */
      options_help = g_option_context_get_help (context, TRUE, NULL);
      g_option_context_free (context);

      if (program_version == TRUE) {
            g_print (VERSION "\n");
            return 0;
      }

      if (argc < 2) {
            g_print (options_help);
            return 1;
      }

      pk_debug_init (verbose);
      loop = g_main_loop_new (NULL, FALSE);

      pconnection = pk_connection_new ();
      g_signal_connect (pconnection, "connection-changed",
                    G_CALLBACK (pk_connection_changed_cb), loop);

      client = pk_client_new ();
      g_signal_connect (client, "package",
                    G_CALLBACK (pk_console_package_cb), NULL);
      g_signal_connect (client, "transaction",
                    G_CALLBACK (pk_console_transaction_cb), NULL);
      g_signal_connect (client, "description",
                    G_CALLBACK (pk_console_description_cb), NULL);
      g_signal_connect (client, "files",
                    G_CALLBACK (pk_console_files_cb), NULL);
      g_signal_connect (client, "repo-signature-required",
                    G_CALLBACK (pk_console_repo_signature_required_cb), NULL);
      g_signal_connect (client, "update-detail",
                    G_CALLBACK (pk_console_update_detail_cb), NULL);
      g_signal_connect (client, "repo-detail",
                    G_CALLBACK (pk_console_repo_detail_cb), NULL);
      g_signal_connect (client, "progress-changed",
                    G_CALLBACK (pk_console_progress_changed_cb), NULL);
      g_signal_connect (client, "finished",
                    G_CALLBACK (pk_console_finished_cb), NULL);
      g_signal_connect (client, "error-code",
                    G_CALLBACK (pk_console_error_code_cb), NULL);

      role_list = pk_client_get_actions (client);
      pk_debug ("actions=%s", pk_enum_list_to_string (role_list));

      /* run the commands */
      pk_console_process_commands (client, argc, argv, !nowait, &error);
      if (error != NULL) {
            g_print ("Error:\n  %s\n\n", error->message);
            g_error_free (error);
            g_print (options_help);
      }

      g_free (options_help);
      g_object_unref (client);

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index