[PackageKit-commit] packagekit: Branch 'master' - 14 commits

Richard Hughes hughsient at kemper.freedesktop.org
Mon Apr 14 11:44:17 PDT 2008


 backends/dummy/pk-backend-dummy.c   |   47 ++
 backends/poldek/pk-backend-poldek.c |  129 +++++++
 backends/yum/helpers/yumBackend.py  |    2 
 backends/zypp/pk-backend-zypp.cpp   |   54 ++-
 backends/zypp/zypp-utils.cpp        |   43 ++
 backends/zypp/zypp-utils.h          |    5 
 client/pk-console.c                 |  633 ++++++++++++++++++++----------------
 contrib/pk-completion.bash          |   63 +--
 data/Makefile.am                    |    3 
 docs/html/pk-faq.html               |    9 
 docs/spec/pk-concepts.xml           |    4 
 docs/spec/pk-signals.xml            |   46 ++
 libpackagekit/pk-client.c           |   47 ++
 libpackagekit/pk-client.h           |    5 
 libpackagekit/pk-debug.h            |    6 
 libpackagekit/pk-enum.c             |    9 
 libpackagekit/pk-enum.h             |    7 
 src/pk-backend-dbus.c               |   27 +
 src/pk-backend.c                    |   45 ++
 src/pk-backend.h                    |    7 
 src/pk-interface-transaction.xml    |    6 
 src/pk-transaction.c                |   31 +
 tools/add-error-enum.sh             |    2 
 23 files changed, 869 insertions(+), 361 deletions(-)

New commits:
commit f0101f19a8f2493aef13691773e602a1cebc09cb
Author: Marcin Banasiak <megabajt at pld-linux.org>
Date:   Mon Apr 14 20:09:21 2008 +0200

    poldek: add UpdateSystem

diff --git a/backends/poldek/pk-backend-poldek.c b/backends/poldek/pk-backend-poldek.c
index f16af59..e81418e 100644
--- a/backends/poldek/pk-backend-poldek.c
+++ b/backends/poldek/pk-backend-poldek.c
@@ -2020,6 +2020,133 @@ backend_update_packages (PkBackend *backend, gchar **package_ids)
 }
 
 /**
+ * backend_update_system:
+ **/
+static gboolean
+backend_update_system_thread (PkBackendThread *thread, gpointer data)
+{
+	TsData			*td = (TsData *)data;
+	PkBackend		*backend;
+	struct vf_progress	vf_progress;
+	struct poldek_ts	*ts;
+	struct poclidek_rcmd	*rcmd;
+	tn_array		*upkgs;
+	gint			i;
+	gboolean		update_cancelled = FALSE;
+
+	setup_vf_progress (&vf_progress, td);
+
+	/* get current backend */
+	backend = pk_backend_thread_get_backend (thread);
+	g_return_val_if_fail (backend != NULL, FALSE);
+
+	/* setup callbacks */
+	poldek_configure (ctx, POLDEK_CONF_TSCONFIRM_CB, ts_confirm, td);
+
+	/* get packages to update */
+	pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY);
+
+	rcmd = poclidek_rcmd_new (cctx, NULL);
+
+	if (poclidek_rcmd_execline (rcmd, "cd /all-avail; ls -q -u")) {
+		upkgs = poclidek_rcmd_get_packages (rcmd);
+
+		/* return only the newest packages */
+		do_newest (upkgs);
+
+		/* remove from array packages marked as blocked */
+		i = 0;
+
+		while (i < n_array_size (upkgs)) {
+			struct pkg	*pkg = n_array_nth (upkgs, i);
+
+			if (pkg->flags & PKG_HELD) {
+				n_array_remove_nth (upkgs, i);
+				continue;
+			}
+
+			i++;
+		}
+
+		poclidek_rcmd_free (rcmd);
+
+		/* start */
+		pk_backend_set_percentage (backend, 1);
+		td->pd->stepvalue = (float)100 / (float)n_array_size (upkgs);
+
+		for (i = 0; i < n_array_size (upkgs); i++) {
+			struct pkg	*pkg = n_array_nth (upkgs, i);
+			gchar		*command;
+
+			pk_backend_set_status (backend, PK_STATUS_ENUM_DEP_RESOLVE);
+
+			pk_backend_set_sub_percentage (backend, 0);
+
+			ts = poldek_ts_new (ctx, 0);
+			rcmd = poclidek_rcmd_new (cctx, ts);
+
+			command = g_strdup_printf ("upgrade %s-%s-%s.%s", pkg->name, pkg->ver, pkg->rel, pkg_arch (pkg));
+
+			if (!poclidek_rcmd_execline (rcmd, command)) {
+				gchar	*error;
+
+				error = g_strdup_printf ("Cannot update %s-%s-%s.%s", pkg->name, pkg->ver, pkg->rel, pkg_arch (pkg));
+
+				pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, error);
+				update_cancelled = TRUE;
+
+				g_free (error);
+			}
+
+			g_free (command);
+
+			poclidek_rcmd_free (rcmd);
+			poldek_ts_free (ts);
+
+			if (update_cancelled)
+				break;
+		}
+
+		td->pd->percentage = (gint)((float)(i + 1) * td->pd->stepvalue);
+
+		if (td->pd->percentage > 1)
+			pk_backend_set_percentage (backend, td->pd->percentage);
+	}
+
+	if (!update_cancelled)
+		pk_backend_set_percentage (backend, 100);
+
+	g_free (td->pd);
+	g_free (td);
+
+	pk_backend_finished (backend);
+
+	return TRUE;
+}
+
+static void
+backend_update_system (PkBackend *backend)
+{
+	TsData	*data = g_new0 (TsData, 1);
+
+	g_return_if_fail (backend != NULL);
+
+	if (pk_network_is_online (network) == FALSE) {
+		pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot update system when offline!");
+		pk_backend_finished (backend);
+
+		g_free (data);
+
+		return;
+	}
+
+	data->pd = g_new0 (PercentageData, 1);
+	data->type = TS_TYPE_ENUM_UPDATE;
+
+	pk_backend_thread_create (thread, backend_update_system_thread, data);
+}
+
+/**
  * backend_get_repo_list:
  */
 static void
@@ -2083,7 +2210,7 @@ PK_BACKEND_OPTIONS (
 	backend_search_name,				/* search_name */
 	NULL,						/* service pack */
 	backend_update_packages,			/* update_packages */
-	NULL,						/* update_system */
+	backend_update_system,				/* update_system */
 	NULL						/* what_provides */
 );
 
commit f7fa071dc7fc397ba19d8090366bb350950467f0
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Mon Apr 14 12:42:41 2008 -0400

    Add VOSTROM public license.

diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
index 4bb3f28..d661850 100644
--- a/libpackagekit/pk-enum.c
+++ b/libpackagekit/pk-enum.c
@@ -387,6 +387,7 @@ static PkEnumMatch enum_free_licenses[] = {
 	{PK_LICENSE_ENUM_MPLUS,                "mplus"},
 	{PK_LICENSE_ENUM_STIX,                 "STIX"},
 	{PK_LICENSE_ENUM_XANO,                 "XANO"},
+	{PK_LICENSE_ENUM_VOSTROM,              "VOSTROM"},
 	{0, NULL}
 };
 
diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
index 5e25e4a..068f5e8 100644
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@ -461,6 +461,7 @@ typedef enum {
 	PK_LICENSE_ENUM_MPLUS,
 	PK_LICENSE_ENUM_STIX,
 	PK_LICENSE_ENUM_XANO,
+	PK_LICENSE_ENUM_VOSTROM,
 	PK_LICENSE_ENUM_UNKNOWN
 } PkLicenseEnum;
 
commit 14780258a01d7c04aa329c9fbf9481cd25fc9c35
Merge: 94112f4... 8e86406...
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Mon Apr 14 12:40:41 2008 -0400

    Merge my changes.

diff --cc libpackagekit/pk-enum.c
index 3bf0921,be6e566..4bb3f28
--- a/libpackagekit/pk-enum.c
+++ b/libpackagekit/pk-enum.c
@@@ -133,10 -133,10 +133,11 @@@ static PkEnumMatch enum_error[] = 
  	{PK_ERROR_ENUM_CANNOT_GET_LOCK,         "cannot-get-lock"},
  	{PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE,   "no-packages-to-update"},
  	{PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG,        "cannot-write-repo-config"},
 -	{PK_ERROR_LOCAL_INSTALL_FAILED,         "local-install-failed"},
 -	{PK_ERROR_BAD_GPG_SIGNATURE,            "bad-gpg-signature"},
 -	{PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,	"cannot-install-source-package"},
 +	{PK_ERROR_ENUM_LOCAL_INSTALL_FAILED,    "local-install-failed"},
 +	{PK_ERROR_ENUM_BAD_GPG_SIGNATURE,       "bad-gpg-signature"},
 +	{PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,   "cannot-install-source-package"},
 +	{PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR,        "repo-configuration-error"},
+ 	{PK_ERROR_ENUM_NO_LICENSE_AGREEMENT,	"no-license-agreement"},
  	{0, NULL}
  };
  
diff --cc libpackagekit/pk-enum.h
index 159cda8,814ae21..5e25e4a
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@@ -222,10 -222,10 +222,11 @@@ typedef enum 
  	PK_ERROR_ENUM_CANNOT_GET_LOCK,
  	PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE,
  	PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG,
 -	PK_ERROR_LOCAL_INSTALL_FAILED,
 -	PK_ERROR_BAD_GPG_SIGNATURE,
 +	PK_ERROR_ENUM_LOCAL_INSTALL_FAILED,
 +	PK_ERROR_ENUM_BAD_GPG_SIGNATURE,
  	PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,
 +	PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR,
+ 	PK_ERROR_ENUM_NO_LICENSE_AGREEMENT,
  	PK_ERROR_ENUM_UNKNOWN
  } PkErrorCodeEnum;
  
commit 8e86406166288c91abb01916008d0dca6b437c80
Author: Stefan Haas <shaas at suse.de>
Date:   Mon Apr 14 17:59:05 2008 +0200

    added license handling stuff

diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index c286b18..0a78222 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -540,6 +540,22 @@ zypp_perform_execution (PkBackend *backend, PerformType type, gboolean force)
                                 break;
                 };
 
+		// look for licenses to confirm
+
+		zypp::ResPool pool = zypp::ResPool::instance ();
+		for (zypp::ResPool::const_iterator it = pool.begin (); it != pool.end (); it++) {
+			if (it->status () == zypp::ResStatus::toBeInstalled && !((*it)->licenseToConfirm ().empty ())) {
+				gchar *package_id = zypp_build_package_id_from_resolvable (it->satSolvable ());
+				pk_backend_eula_required (backend,
+						"",	//eula_id
+						package_id,
+						(*it)->vendor ().c_str (),
+						(*it)->licenseToConfirm ().c_str ()); 
+				pk_backend_error_code (backend, PK_ERROR_ENUM_NO_LICENSE_AGREEMENT, "You've to agree/decline a license");
+				g_free (package_id);
+			}
+		}
+
                 // Perform the installation
                 zypp::ZYppCommitPolicy policy;
                 policy.restrictToMedia (0);	// 0 - install all packages regardless to media
commit 898667242e276c15e199d70e0ba1de8f165d07a5
Merge: 532faf0... ea1a73f...
Author: Stefan Haas <shaas at suse.de>
Date:   Mon Apr 14 17:38:47 2008 +0200

    Merge branch 'master' of git+ssh://shaas@git.packagekit.org/srv/git/PackageKit

commit 532faf0e7aeb91f2a6285feaac786bdda695645c
Author: Stefan Haas <shaas at suse.de>
Date:   Mon Apr 14 17:36:00 2008 +0200

    changed get_updates and get_update_detail

diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp
index 42de58d..13731f5 100644
--- a/backends/zypp/pk-backend-zypp.cpp
+++ b/backends/zypp/pk-backend-zypp.cpp
@@ -665,10 +665,21 @@ backend_get_updates_thread (PkBackendThread *thread, gpointer data)
 
 		// Emit the package
 
-		PkInfoEnum infoEnum = PK_INFO_ENUM_AVAILABLE;
-
-		if (zypp::isKind<zypp::Patch>(res))
-			infoEnum = PK_INFO_ENUM_SECURITY;
+		PkInfoEnum infoEnum = PK_INFO_ENUM_ENHANCEMENT;
+
+		if (zypp::isKind<zypp::Patch>(res)) {
+			zypp::Patch::constPtr patch = zypp::asKind<zypp::Patch>(res);
+			if (patch->category () == "recommended") {
+				infoEnum = PK_INFO_ENUM_IMPORTANT;
+			}else if (patch->category () == "optional") {
+				infoEnum = PK_INFO_ENUM_LOW;
+			}else if (patch->category () == "security") {
+				infoEnum = PK_INFO_ENUM_SECURITY;
+			}else{
+				infoEnum = PK_INFO_ENUM_NORMAL;
+			}
+		}
+		
 
 		gchar *package_id = zypp_build_package_id_from_resolvable (res->satSolvable ());
 		pk_backend_package (backend,
@@ -722,17 +733,16 @@ backend_get_update_detail_thread (PkBackendThread *thread, gpointer data)
 	zypp::sat::Solvable solvable = zypp_get_package_by_id (d->package_id);
 
 	zypp::Capabilities obs = solvable.obsoletes ();
+	zypp::Capabilities upd = solvable.freshens ();
 
-	gchar *obsoletes = new gchar ();
-
-	for (zypp::Capabilities::const_iterator it = obs.begin (); it != obs.end (); it++) {
-		g_strlcat(obsoletes, it->c_str (), (strlen (obsoletes) + strlen (it->c_str ()) + 1));
-		g_strlcat(obsoletes, ";", (strlen (obsoletes) + 2));
-	}
+	gchar *obsoletes = zypp_build_package_id_capabilities (obs);
+	gchar *updates = zypp_build_package_id_capabilities (upd);
 
 	PkRestartEnum restart = PK_RESTART_ENUM_NONE;
 
 	zypp::PoolItem item = zypp::ResPool::instance ().find (solvable);
+	
+	gchar *bugzilla = new gchar ();
 
 	if (zypp::isKind<zypp::Patch>(solvable)) {
 		zypp::Patch::constPtr patch = zypp::asKind<zypp::Patch>(item);
@@ -741,19 +751,33 @@ backend_get_update_detail_thread (PkBackendThread *thread, gpointer data)
 		}else if (patch->affects_pkg_manager ()) {
 			restart = PK_RESTART_ENUM_SESSION;
 		}
+
+		zypp::Patch::ReferenceIterator it = patch->referencesBegin ();
+
+		if ( it != patch->referencesEnd ())
+			bugzilla = g_strdup(it.href ().c_str ());
+		
+		zypp::sat::SolvableSet content = patch->contents ();
+
+		for (zypp::sat::SolvableSet::const_iterator it = content.begin (); it != content.end (); it++) {
+			obsoletes = g_strconcat (obsoletes, zypp_build_package_id_capabilities (it->obsoletes ()), " ", (gchar *)NULL);
+			updates = g_strconcat (updates, zypp_build_package_id_capabilities (it->freshens ()), " ", (gchar *)NULL);
+		}
 	}
 
 	pk_backend_update_detail (backend,
 				  d->package_id,
-				  "",
-				  "", // CURRENTLY CAUSES SEGFAULT obsoletes,
-				  "", // CURRENTLY CAUSES SEGFAULT solvable.vendor ().c_str (),
-				  "",
-				  "",
+				  updates, 	// updates
+				  obsoletes, 	// CURRENTLY CAUSES SEGFAULT obsoletes,
+				  "", 		// CURRENTLY CAUSES SEGFAULT solvable.vendor ().c_str (),
+				  bugzilla, 	// bugzilla
+				  "", 		// cve
 				  restart,
 				  solvable.lookupStrAttribute (zypp::sat::SolvAttr::description).c_str ());
 
+	g_free (bugzilla);
 	g_free (obsoletes);
+	g_free (updates);
 	pk_package_id_free (pi);
 	g_free (d->package_id);
 	g_free (d);
diff --git a/backends/zypp/zypp-utils.cpp b/backends/zypp/zypp-utils.cpp
index 49e6eba..c286b18 100644
--- a/backends/zypp/zypp-utils.cpp
+++ b/backends/zypp/zypp-utils.cpp
@@ -258,12 +258,9 @@ zypp_get_packages_by_name (const gchar *package_name, const zypp::ResKind kind,
 
 	zypp::ResPool pool = zypp_build_pool (include_local);
 
-        zypp::Capability cap (package_name, kind, zypp::Capability::PARSED);
-        zypp::sat::WhatProvides provs (cap);
-
-        for (zypp::sat::WhatProvides::const_iterator it = provs.begin ();
-                        it != provs.end (); it++) {
-                v->push_back (*it);
+        for (zypp::ResPool::byIdent_iterator it = pool.byIdentBegin (kind, package_name);
+                        it != pool.byIdentEnd (kind, package_name); it++) {
+                v->push_back (it->satSolvable ());
         }
 
 	return v;
@@ -482,6 +479,8 @@ zypp_get_patches ()
         zypp::ZYpp::Ptr zypp;
         zypp = get_zypp ();
 
+	zypp->resolver ()->resolvePool ();
+
         for (zypp::ResPoolProxy::const_iterator it = zypp->poolProxy ().byKindBegin<zypp::Patch>();
                         it != zypp->poolProxy ().byKindEnd<zypp::Patch>(); it ++) {
                 // check if patch is needed 
@@ -623,3 +622,19 @@ zypp_convert_set_char (std::set<zypp::sat::Solvable> *set)
 
         return array;
 }
+
+gchar *
+zypp_build_package_id_capabilities (zypp::Capabilities caps)
+{
+	gchar * package_ids = new gchar ();
+
+	zypp::sat::WhatProvides provs (caps);
+
+	for (zypp::sat::WhatProvides::const_iterator it = provs.begin (); it != provs.end (); it++) {
+		gchar *package_id = zypp_build_package_id_from_resolvable (*it);
+		package_ids = g_strconcat (package_ids, package_id, " ", (gchar *)NULL);
+		g_free (package_id);
+	}
+
+	return package_ids;
+}
diff --git a/backends/zypp/zypp-utils.h b/backends/zypp/zypp-utils.h
index ff40c3a..c2b710d 100644
--- a/backends/zypp/zypp-utils.h
+++ b/backends/zypp/zypp-utils.h
@@ -130,5 +130,10 @@ void zypp_emit_packages_in_list (PkBackend *backend, std::vector<zypp::sat::Solv
   * convert a std::set<zypp::sat::Solvable to gchar ** array
   */
 gchar ** zypp_convert_set_char (std::set<zypp::sat::Solvable> *set);
+
+/**
+  * build string of package_id's seperated by blanks out of the capabilities of a solvable
+  */
+gchar * zypp_build_package_id_capabilities (zypp::Capabilities caps);
 #endif // _ZYPP_UTILS_H_
 
commit 94112f4dbe435c7bf0f0087a4415f46b714e2796
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Mon Apr 14 11:21:25 2008 -0400

    Fix enum names.

diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
index 1de4bd9..3bf0921 100644
--- a/libpackagekit/pk-enum.c
+++ b/libpackagekit/pk-enum.c
@@ -133,8 +133,8 @@ static PkEnumMatch enum_error[] = {
 	{PK_ERROR_ENUM_CANNOT_GET_LOCK,         "cannot-get-lock"},
 	{PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE,   "no-packages-to-update"},
 	{PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG,        "cannot-write-repo-config"},
-	{PK_ERROR_LOCAL_INSTALL_FAILED,         "local-install-failed"},
-	{PK_ERROR_BAD_GPG_SIGNATURE,            "bad-gpg-signature"},
+	{PK_ERROR_ENUM_LOCAL_INSTALL_FAILED,    "local-install-failed"},
+	{PK_ERROR_ENUM_BAD_GPG_SIGNATURE,       "bad-gpg-signature"},
 	{PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,   "cannot-install-source-package"},
 	{PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR,        "repo-configuration-error"},
 	{0, NULL}
diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
index c82cded..159cda8 100644
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@ -222,8 +222,8 @@ typedef enum {
 	PK_ERROR_ENUM_CANNOT_GET_LOCK,
 	PK_ERROR_ENUM_NO_PACKAGES_TO_UPDATE,
 	PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG,
-	PK_ERROR_LOCAL_INSTALL_FAILED,
-	PK_ERROR_BAD_GPG_SIGNATURE,
+	PK_ERROR_ENUM_LOCAL_INSTALL_FAILED,
+	PK_ERROR_ENUM_BAD_GPG_SIGNATURE,
 	PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,
 	PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR,
 	PK_ERROR_ENUM_UNKNOWN
commit 235371a7b694b0b5dec174cada4baad66a65a73a
Author: Robin Norwood <rnorwood at redhat.com>
Date:   Mon Apr 14 11:15:42 2008 -0400

    Add repo configuration error enum.

diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py
index 31bd44d..7f5ea53 100644
--- a/backends/yum/helpers/yumBackend.py
+++ b/backends/yum/helpers/yumBackend.py
@@ -838,6 +838,8 @@ class PackageKitYumBackend(PackageKitBaseBackend):
             #we might have a rounding error
             self.percentage(100)
 
+        except yum.Errors.RepoError, e:
+            self.error(ERROR_REPO_CONFIGURATION_ERROR, str(e))
         except yum.Errors.YumBaseError, e:
             self.error(ERROR_UNKNOWN,str(e))
 
diff --git a/docs/spec/pk-concepts.xml b/docs/spec/pk-concepts.xml
index 73137d9..9dd0823 100644
--- a/docs/spec/pk-concepts.xml
+++ b/docs/spec/pk-concepts.xml
@@ -294,6 +294,10 @@
             <entry>The repository name could not be found</entry>
           </row>
           <row>
+            <entry><literal>repo-configuration-error</literal></entry>
+            <entry>One of the enabled repositories has invalid configuration</entry>
+          </row>
+          <row>
             <entry><literal>cannot-remove-system-package</literal></entry>
             <entry>
               Could not remove a protected system package that is needed for
diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
index 10298ab..1de4bd9 100644
--- a/libpackagekit/pk-enum.c
+++ b/libpackagekit/pk-enum.c
@@ -135,7 +135,8 @@ static PkEnumMatch enum_error[] = {
 	{PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG,        "cannot-write-repo-config"},
 	{PK_ERROR_LOCAL_INSTALL_FAILED,         "local-install-failed"},
 	{PK_ERROR_BAD_GPG_SIGNATURE,            "bad-gpg-signature"},
-	{PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,       "cannot-install-source-package"},
+	{PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,   "cannot-install-source-package"},
+	{PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR,        "repo-configuration-error"},
 	{0, NULL}
 };
 
diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
index fd2b1ac..c82cded 100644
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@ -225,6 +225,7 @@ typedef enum {
 	PK_ERROR_LOCAL_INSTALL_FAILED,
 	PK_ERROR_BAD_GPG_SIGNATURE,
 	PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,
+	PK_ERROR_ENUM_REPO_CONFIGURATION_ERROR,
 	PK_ERROR_ENUM_UNKNOWN
 } PkErrorCodeEnum;
 
commit ea1a73ff699e2f19425ca9dc4214b700d174970b
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Apr 14 15:43:22 2008 +0100

    add a EulaRequired signal

diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c
index 71649f1..bb833c2 100644
--- a/backends/dummy/pk-backend-dummy.c
+++ b/backends/dummy/pk-backend-dummy.c
@@ -303,14 +303,45 @@ static void
 backend_install_package (PkBackend *backend, const gchar *package_id)
 {
 	g_return_if_fail (backend != NULL);
-
-	if (!_has_signature && pk_strequal (package_id, "vips-doc;7.12.4-2.fc8;noarch;linva")) {
-		pk_backend_repo_signature_required (backend, package_id, "updates", "http://example.com/gpgkey",
-						    "Test Key (Fedora) fedora at example.com", "BB7576AC",
-						    "D8CC 06C2 77EC 9C53 372F  C199 B1EE 1799 F24F 1B08",
-						    "2007-10-04", PK_SIGTYPE_ENUM_GPG);
-		pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE,
-				       "GPG signed package could not be verified");
+	const gchar *license_agreement;
+	const gchar *eula_id;
+
+	if (pk_strequal (package_id, "vips-doc;7.12.4-2.fc8;noarch;linva")) {
+		if (!_has_signature) {
+			pk_backend_repo_signature_required (backend, package_id, "updates",
+							    "http://example.com/gpgkey",
+							    "Test Key (Fedora) fedora at example.com",
+							    "BB7576AC",
+							    "D8CC 06C2 77EC 9C53 372F C199 B1EE 1799 F24F 1B08",
+							    "2007-10-04", PK_SIGTYPE_ENUM_GPG);
+			pk_backend_error_code (backend, PK_ERROR_ENUM_GPG_FAILURE,
+					       "GPG signed package could not be verified");
+			pk_backend_finished (backend);
+			return;
+		}
+		eula_id = "eula_hughsie_dot_com";
+		license_agreement = "Narrator: In A.D. 2101, war was beginning.\n"
+				    "Captain: What happen ?\n"
+				    "Mechanic: Somebody set up us the bomb.\n\n"
+				    "Operator: We get signal.\n"
+				    "Captain: What !\n"
+				    "Operator: Main screen turn on.\n"
+				    "Captain: It's you !!\n"
+				    "CATS: How are you gentlemen !!\n"
+				    "CATS: All your base are belong to us.\n"
+				    "CATS: You are on the way to destruction.\n\n"
+				    "Captain: What you say !!\n"
+				    "CATS: You have no chance to survive make your time.\n"
+				    "CATS: Ha Ha Ha Ha ....\n\n"
+				    "Operator: Captain!! *\n"
+				    "Captain: Take off every 'ZIG' !!\n"
+				    "Captain: You know what you doing.\n"
+				    "Captain: Move 'ZIG'.\n"
+				    "Captain: For great justice.\n";
+		pk_backend_eula_required (backend, eula_id, package_id,
+					  "CATS Inc.", license_agreement);
+		pk_backend_error_code (backend, PK_ERROR_ENUM_NO_LICENSE_AGREEMENT,
+				       "licence not installed so cannot install");
 		pk_backend_finished (backend);
 		return;
 	}
diff --git a/client/pk-console.c b/client/pk-console.c
index 224ab66..72fb84b 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -886,6 +886,33 @@ pk_console_repo_signature_required_cb (PkClient *client, const gchar *package_id
 }
 
 /**
+ * pk_console_eula_required_cb:
+ **/
+static void
+pk_console_eula_required_cb (PkClient *client, const gchar *eula_id, const gchar *package_id,
+			     const gchar *vendor_name, const gchar *license_agreement, gpointer data)
+{
+	gboolean import;
+
+	if (awaiting_space) {
+		g_print ("\n");
+	}
+	g_print ("Eula Required\n");
+	g_print ("Eula:        %s\n", eula_id);
+	g_print ("Package:     %s\n", package_id);
+	g_print ("Vendor:      %s\n", vendor_name);
+	g_print ("Agreement:   %s\n", license_agreement);
+
+	/* get user input */
+	import = pk_console_get_prompt (_("Do you agree?"), FALSE);
+	if (!import) {
+		g_print ("%s\n", _("Did not agree to licence, task will fail"));
+		return;
+	}
+	g_print ("Importing licences is not yet supported!\n");
+}
+
+/**
  * pk_connection_changed_cb:
  **/
 static void
@@ -1122,6 +1149,8 @@ main (int argc, char *argv[])
 			  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, "eula-required",
+			  G_CALLBACK (pk_console_eula_required_cb), NULL);
 	g_signal_connect (client, "update-detail",
 			  G_CALLBACK (pk_console_update_detail_cb), NULL);
 	g_signal_connect (client, "repo-detail",
diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html
index 91ffc76..084a5d8 100644
--- a/docs/html/pk-faq.html
+++ b/docs/html/pk-faq.html
@@ -661,11 +661,10 @@ The reasons for this are as follows:
 </p>
 <p>
 EULAs or other agreements will have to be agreed to <b>before</b> the
-transaction is processed.
-EULAs are legally questionable (because the files are already installed) and
-only the user that installing the software is ever shown them.
-If EULAs are required, they should be shown per-user - i.e. the first time an
-application is run.
+transaction is processed using the <code>EulaRequired</code> signal.
+</p>
+<p>
+EULAs should preferably be shown per-user - i.e. the first time an application is run.
 </p>
 <p>
 PackageKit will not install packages with broken maintainer scripts that
diff --git a/docs/spec/pk-signals.xml b/docs/spec/pk-signals.xml
index 7b8939f..869ba19 100644
--- a/docs/spec/pk-signals.xml
+++ b/docs/spec/pk-signals.xml
@@ -437,6 +437,10 @@
         </thead>
         <tbody>
           <row>
+            <entry><literal>package_id</literal></entry>
+            <entry>A package ID for the package that is trying to be installed</entry>
+          </row>
+          <row>
             <entry><literal>repository_name</literal></entry>
             <entry>
               The name of the repository associated with the provided key
@@ -471,5 +475,47 @@
     </informaltable>
   </sect1>
 
+  <sect1 id="signals-eula-required">
+    <title>EulaRequired</title>
+    <para>
+      Some backends support EULAs, which have to be agreed to before the install can proceed.
+    </para>
+    <informaltable>
+      <tgroup cols="2">
+        <thead>
+          <row>
+            <entry>Option</entry>
+            <entry>Description</entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry><literal>eula_id</literal></entry>
+            <entry>
+              The <literal>eula_id</literal> which identifies the EULA - this is provided
+              so that if a specific EULA has previously agreed to a EULA from Acme Corp it is
+              not asked again.
+              An example <literal>eula_id</literal>'s is <literal>vmware5_single_user</literal>.
+            </entry>
+          </row>
+          <row>
+            <entry><literal>package_id</literal></entry>
+            <entry>A package ID for the package that is trying to be installed</entry>
+          </row>
+          <row>
+            <entry><literal>vendor_name</literal></entry>
+            <entry>
+              The vendor that is providing the EULA.
+            </entry>
+          </row>
+          <row>
+            <entry><literal>license_agreement</literal></entry>
+            <entry>The full text EULA.</entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </informaltable>
+  </sect1>
+
 </chapter>
 
diff --git a/libpackagekit/pk-client.c b/libpackagekit/pk-client.c
index f0c01e7..fd6b08e 100644
--- a/libpackagekit/pk-client.c
+++ b/libpackagekit/pk-client.c
@@ -106,6 +106,7 @@ typedef enum {
 	PK_CLIENT_STATUS_CHANGED,
 	PK_CLIENT_UPDATE_DETAIL,
 	PK_CLIENT_REPO_SIGNATURE_REQUIRED,
+	PK_CLIENT_EULA_REQUIRED,
 	PK_CLIENT_CALLER_ACTIVE_CHANGED,
 	PK_CLIENT_REPO_DETAIL,
 	PK_CLIENT_ALLOW_CANCEL,
@@ -584,7 +585,7 @@ pk_client_repo_signature_required_cb (DBusGProxy *proxy, const gchar *package_id
 {
 	g_return_if_fail (PK_IS_CLIENT (client));
 
-	pk_debug ("emit repo_signature_required %s, %s, %s, %s, %s, %s, %s, %s",
+	pk_debug ("emit repo-signature-required %s, %s, %s, %s, %s, %s, %s, %s",
 		  package_id, repository_name, key_url, key_userid,
 		  key_id, key_fingerprint, key_timestamp, type_text);
 
@@ -593,6 +594,22 @@ pk_client_repo_signature_required_cb (DBusGProxy *proxy, const gchar *package_id
 }
 
 /**
+ * pk_client_eula_required_cb:
+ **/
+static void
+pk_client_eula_required_cb (DBusGProxy *proxy, const gchar *eula_id, const gchar *package_id,
+			    const gchar *vendor_name, const gchar *license_agreement, PkClient *client)
+{
+	g_return_if_fail (PK_IS_CLIENT (client));
+
+	pk_debug ("emit eula-required %s, %s, %s, %s",
+		  eula_id, package_id, vendor_name, license_agreement);
+
+	g_signal_emit (client, signals [PK_CLIENT_EULA_REQUIRED], 0,
+		       eula_id, package_id, vendor_name, license_agreement);
+}
+
+/**
  * pk_client_repo_detail_cb:
  **/
 static void
@@ -2921,6 +2938,8 @@ pk_client_set_tid (PkClient *client, const gchar *tid, GError **error)
 				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (proxy, "EulaRequired",
+				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
 	dbus_g_proxy_add_signal (proxy, "RepoDetail", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INVALID);
 	dbus_g_proxy_add_signal (proxy, "ErrorCode", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
 	dbus_g_proxy_add_signal (proxy, "RequireRestart", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
@@ -2946,6 +2965,8 @@ pk_client_set_tid (PkClient *client, const gchar *tid, GError **error)
 				     G_CALLBACK (pk_client_files_cb), client, NULL);
 	dbus_g_proxy_connect_signal (proxy, "RepoSignatureRequired",
 				     G_CALLBACK (pk_client_repo_signature_required_cb), client, NULL);
+	dbus_g_proxy_connect_signal (proxy, "EulaRequired",
+				     G_CALLBACK (pk_client_eula_required_cb), client, NULL);
 	dbus_g_proxy_connect_signal (proxy, "RepoDetail",
 				     G_CALLBACK (pk_client_repo_detail_cb), client, NULL);
 	dbus_g_proxy_connect_signal (proxy, "ErrorCode",
@@ -3098,6 +3119,7 @@ pk_client_class_init (PkClientClass *klass)
 	/**
 	 * PkClient::repo-signature-required:
 	 * @client: the #PkClient instance that emitted the signal
+	 * @package_id: the package_id of the package
 	 * @repository_name: the name of the repository
 	 * @key_url: the URL of the repository
 	 * @key_userid: the user signing the repository
@@ -3117,6 +3139,22 @@ pk_client_class_init (PkClientClass *klass)
 			      G_TYPE_NONE, 8, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 			      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);
 	/**
+	 * PkClient::eula-required:
+	 * @client: the #PkClient instance that emitted the signal
+	 * @eula_id: the EULA id, e.g. <literal>vmware5_single_user</literal>
+	 * @package_id: the package_id of the package
+	 * @vendor_name: the Vendor name, e.g. Acme Corp.
+	 * @license_agreement: the text of the license agreement
+	 *
+	 * The ::eula signal is emitted when the transaction needs to fail for a EULA prompt.
+	 **/
+	signals [PK_CLIENT_EULA_REQUIRED] =
+		g_signal_new ("eula-required",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (PkClientClass, eula_required),
+			      NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING_STRING,
+			      G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+	/**
 	 * PkClient::repo-detail:
 	 * @client: the #PkClient instance that emitted the signal
 	 * @repo_id: the ID of the repository
@@ -3274,6 +3312,8 @@ pk_client_disconnect_proxy (PkClient *client)
 				        G_CALLBACK (pk_client_files_cb), client);
 	dbus_g_proxy_disconnect_signal (client->priv->proxy, "RepoSignatureRequired",
 				        G_CALLBACK (pk_client_repo_signature_required_cb), client);
+	dbus_g_proxy_disconnect_signal (client->priv->proxy, "EulaRequired",
+				        G_CALLBACK (pk_client_eula_required_cb), client);
 	dbus_g_proxy_disconnect_signal (client->priv->proxy, "ErrorCode",
 				        G_CALLBACK (pk_client_error_code_cb), client);
 	dbus_g_proxy_disconnect_signal (client->priv->proxy, "RequireRestart",
@@ -3427,6 +3467,11 @@ pk_client_init (PkClient *client)
 					   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64,
 					   G_TYPE_INVALID);
 
+	/* EulaRequired */
+	dbus_g_object_register_marshaller (pk_marshal_VOID__STRING_STRING_STRING_STRING,
+					   G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING,
+					   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
 	/* Files */
 	dbus_g_object_register_marshaller (pk_marshal_VOID__STRING_STRING,
 					   G_TYPE_NONE, G_TYPE_STRING,
diff --git a/libpackagekit/pk-client.h b/libpackagekit/pk-client.h
index 307a08c..2d7dfe7 100644
--- a/libpackagekit/pk-client.h
+++ b/libpackagekit/pk-client.h
@@ -123,6 +123,11 @@ struct _PkClientClass
 							 const gchar	*key_fingerprint,
 							 const gchar	*key_timestamp,
 							 PkSigTypeEnum	 type);
+	void		(* eula_required)		(PkClient	*client,
+							 const gchar	*eula_id,
+							 const gchar	*package_id,
+							 const gchar	*vendor_name,
+							 const gchar	*license_agreement);
 	void		(* repo_detail)			(PkClient	*client,
 							 const gchar	*repo_id,
 							 const gchar	*description,
diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c
index 10298ab..be6e566 100644
--- a/libpackagekit/pk-enum.c
+++ b/libpackagekit/pk-enum.c
@@ -135,7 +135,8 @@ static PkEnumMatch enum_error[] = {
 	{PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG,        "cannot-write-repo-config"},
 	{PK_ERROR_LOCAL_INSTALL_FAILED,         "local-install-failed"},
 	{PK_ERROR_BAD_GPG_SIGNATURE,            "bad-gpg-signature"},
-	{PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,       "cannot-install-source-package"},
+	{PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,	"cannot-install-source-package"},
+	{PK_ERROR_ENUM_NO_LICENSE_AGREEMENT,	"no-license-agreement"},
 	{0, NULL}
 };
 
diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h
index fd2b1ac..814ae21 100644
--- a/libpackagekit/pk-enum.h
+++ b/libpackagekit/pk-enum.h
@@ -225,6 +225,7 @@ typedef enum {
 	PK_ERROR_LOCAL_INSTALL_FAILED,
 	PK_ERROR_BAD_GPG_SIGNATURE,
 	PK_ERROR_ENUM_CANNOT_INSTALL_SOURCE_PACKAGE,
+	PK_ERROR_ENUM_NO_LICENSE_AGREEMENT,
 	PK_ERROR_ENUM_UNKNOWN
 } PkErrorCodeEnum;
 
diff --git a/src/pk-backend-dbus.c b/src/pk-backend-dbus.c
index cae34bd..456a1df 100644
--- a/src/pk-backend-dbus.c
+++ b/src/pk-backend-dbus.c
@@ -254,6 +254,19 @@ pk_backend_dbus_repo_signature_required_cb (DBusGProxy *proxy, const gchar *pack
 }
 
 /**
+ * pk_backend_dbus_eula_required_cb:
+ **/
+static void
+pk_backend_dbus_eula_required_cb (DBusGProxy *proxy, const gchar *eula_id, const gchar *package_id,
+				  const gchar *vendor_name, const gchar *license_agreement,
+				  PkBackendDbus *backend_dbus)
+{
+	pk_debug ("got signal");
+	pk_backend_eula_required (backend_dbus->priv->backend, eula_id,
+				  package_id, vendor_name, license_agreement);
+}
+
+/**
  * pk_backend_dbus_time_reset:
  **/
 static gboolean
@@ -335,6 +348,8 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus)
 					G_CALLBACK (pk_backend_dbus_message_cb), backend_dbus);
 	dbus_g_proxy_disconnect_signal (proxy, "RepoSignatureRequired",
 					G_CALLBACK (pk_backend_dbus_repo_signature_required_cb), backend_dbus);
+	dbus_g_proxy_disconnect_signal (proxy, "EulaRequired",
+					G_CALLBACK (pk_backend_dbus_eula_required_cb), backend_dbus);
 	return TRUE;
 }
 
@@ -396,7 +411,10 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
 	dbus_g_proxy_add_signal (proxy, "RepoSignatureRequired",
 				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-				 G_TYPE_UINT, G_TYPE_INVALID);
+				 G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (proxy, "EulaRequired",
+				 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+				 G_TYPE_STRING, G_TYPE_INVALID);
 
 	/* add callbacks */
 	dbus_g_proxy_connect_signal (proxy, "RepoDetail",
@@ -429,6 +447,8 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service)
 				     G_CALLBACK (pk_backend_dbus_message_cb), backend_dbus, NULL);
 	dbus_g_proxy_connect_signal (proxy, "RepoSignatureRequired",
 				     G_CALLBACK (pk_backend_dbus_repo_signature_required_cb), backend_dbus, NULL);
+	dbus_g_proxy_connect_signal (proxy, "EulaRequired",
+				     G_CALLBACK (pk_backend_dbus_eula_required_cb), backend_dbus, NULL);
 
 	backend_dbus->priv->proxy = proxy;
 
@@ -1366,6 +1386,11 @@ pk_backend_dbus_init (PkBackendDbus *backend_dbus)
 					   G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 					   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID);
 
+	/* EulaRequired */
+	dbus_g_object_register_marshaller (pk_marshal_VOID__STRING_STRING_STRING_STRING,
+					   G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING,
+					   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
 	/* Package */
 	dbus_g_object_register_marshaller (pk_marshal_VOID__STRING_STRING_STRING,
 					   G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
diff --git a/src/pk-backend.c b/src/pk-backend.c
index 7b623a6..d798b72 100644
--- a/src/pk-backend.c
+++ b/src/pk-backend.c
@@ -85,6 +85,7 @@ struct _PkBackendPrivate
 	gboolean		 locked;
 	gboolean		 set_error;
 	gboolean		 set_signature;
+	gboolean		 set_eula;
 	PkRoleEnum		 role; /* this never changes for the lifetime of a transaction */
 	PkStatusEnum		 status; /* this changes */
 	PkExitEnum		 exit;
@@ -111,6 +112,7 @@ enum {
 	PK_BACKEND_UPDATE_DETAIL,
 	PK_BACKEND_ERROR_CODE,
 	PK_BACKEND_REPO_SIGNATURE_REQUIRED,
+	PK_BACKEND_EULA_REQUIRED,
 	PK_BACKEND_REQUIRE_RESTART,
 	PK_BACKEND_MESSAGE,
 	PK_BACKEND_CHANGE_TRANSACTION_DATA,
@@ -902,6 +904,42 @@ pk_backend_repo_signature_required (PkBackend *backend, const gchar *package_id,
 }
 
 /**
+ * pk_backend_eula_required:
+ **/
+gboolean
+pk_backend_eula_required (PkBackend *backend, const gchar *eula_id, const gchar *package_id,
+			  const gchar *vendor_name, const gchar *license_agreement)
+{
+	g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE);
+	g_return_val_if_fail (eula_id != NULL, FALSE);
+	g_return_val_if_fail (package_id != NULL, FALSE);
+	g_return_val_if_fail (vendor_name != NULL, FALSE);
+	g_return_val_if_fail (license_agreement != NULL, FALSE);
+	g_return_val_if_fail (backend->priv->locked != FALSE, FALSE);
+
+	/* have we already set an error? */
+	if (backend->priv->set_error) {
+		pk_warning ("already set error, cannot process");
+		return FALSE;
+	}
+
+	/* check we don't do this more than once */
+	if (backend->priv->set_eula) {
+		pk_warning ("already asked for a signature, cannot process");
+		return FALSE;
+	}
+	backend->priv->set_eula = TRUE;
+
+	pk_debug ("emit eula-required %s, %s, %s, %s",
+		  eula_id, package_id, vendor_name, license_agreement);
+
+	g_signal_emit (backend, signals [PK_BACKEND_EULA_REQUIRED], 0,
+		       eula_id, package_id, vendor_name, license_agreement);
+
+	return TRUE;
+}
+
+/**
  * pk_backend_repo_detail:
  **/
 gboolean
@@ -1375,6 +1413,12 @@ pk_backend_class_init (PkBackendClass *klass)
 			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING_STRING_STRING_STRING_STRING_UINT,
 			      G_TYPE_NONE, 8, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 			      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);
+	signals [PK_BACKEND_EULA_REQUIRED] =
+		g_signal_new ("eula-required",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING_STRING,
+			      G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING,
+			      G_TYPE_STRING, G_TYPE_STRING);
 	signals [PK_BACKEND_FINISHED] =
 		g_signal_new ("finished",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
@@ -1403,6 +1447,7 @@ pk_backend_reset (PkBackend *backend)
 
 	backend->priv->set_error = FALSE;
 	backend->priv->set_signature = FALSE;
+	backend->priv->set_eula = FALSE;
 	backend->priv->allow_cancel = FALSE;
 	backend->priv->finished = FALSE;
 	backend->priv->status = PK_STATUS_ENUM_UNKNOWN;
diff --git a/src/pk-backend.h b/src/pk-backend.h
index 1c9eab4..b6065cf 100644
--- a/src/pk-backend.h
+++ b/src/pk-backend.h
@@ -101,7 +101,7 @@ gboolean 	 pk_backend_files 			(PkBackend 	*backend,
 gboolean	 pk_backend_error_code			(PkBackend	*backend,
 							 PkErrorCodeEnum code,
 							 const gchar	*details, ...);
-gboolean         pk_backend_repo_signature_required     (PkBackend      *backend,
+gboolean         pk_backend_repo_signature_required	(PkBackend      *backend,
 							 const gchar	*package_id,
 							 const gchar    *repository_name,
 							 const gchar    *key_url,
@@ -110,6 +110,11 @@ gboolean         pk_backend_repo_signature_required     (PkBackend      *backend
 							 const gchar    *key_fingerprint,
 							 const gchar    *key_timestamp,
 							 PkSigTypeEnum   type);
+gboolean         pk_backend_eula_required		(PkBackend      *backend,
+							 const gchar	*eula_id,
+							 const gchar    *package_id,
+							 const gchar    *vendor_name,
+							 const gchar    *license_agreement);
 
 /* internal state */
 gboolean	 pk_backend_set_internal		(PkBackend	*backend,
diff --git a/src/pk-interface-transaction.xml b/src/pk-interface-transaction.xml
index 5ec1cba..683da72 100644
--- a/src/pk-interface-transaction.xml
+++ b/src/pk-interface-transaction.xml
@@ -201,6 +201,12 @@
       <arg type="s" name="key_timestamp" direction="out"/>
       <arg type="s" name="type" direction="out"/>
     </signal>
+    <signal name="EulaRequired">
+      <arg type="s" name="eula_id" direction="out"/>
+      <arg type="s" name="package_id" direction="out"/>
+      <arg type="s" name="vendor_name" direction="out"/>
+      <arg type="s" name="license_agreement" direction="out"/>
+    </signal>
     <signal name="RequireRestart">
       <arg type="s" name="type" direction="out"/>
       <arg type="s" name="details" direction="out"/>
diff --git a/src/pk-transaction.c b/src/pk-transaction.c
index dd069f4..190e925 100644
--- a/src/pk-transaction.c
+++ b/src/pk-transaction.c
@@ -115,6 +115,7 @@ struct PkTransactionPrivate
 	guint			 signal_progress_changed;
 	guint			 signal_repo_detail;
 	guint			 signal_repo_signature_required;
+	guint			 signal_eula_required;
 	guint			 signal_require_restart;
 	guint			 signal_status_changed;
 	guint			 signal_update_detail;
@@ -132,6 +133,7 @@ enum {
 	PK_TRANSACTION_PROGRESS_CHANGED,
 	PK_TRANSACTION_REPO_DETAIL,
 	PK_TRANSACTION_REPO_SIGNATURE_REQUIRED,
+	PK_TRANSACTION_EULA_REQUIRED,
 	PK_TRANSACTION_REQUIRE_RESTART,
 	PK_TRANSACTION_STATUS_CHANGED,
 	PK_TRANSACTION_TRANSACTION,
@@ -491,6 +493,7 @@ pk_transaction_finished_cb (PkBackend *backend, PkExitEnum exit, PkTransaction *
 	g_signal_handler_disconnect (transaction->priv->backend, transaction->priv->signal_progress_changed);
 	g_signal_handler_disconnect (transaction->priv->backend, transaction->priv->signal_repo_detail);
 	g_signal_handler_disconnect (transaction->priv->backend, transaction->priv->signal_repo_signature_required);
+	g_signal_handler_disconnect (transaction->priv->backend, transaction->priv->signal_eula_required);
 	g_signal_handler_disconnect (transaction->priv->backend, transaction->priv->signal_require_restart);
 	g_signal_handler_disconnect (transaction->priv->backend, transaction->priv->signal_status_changed);
 	g_signal_handler_disconnect (transaction->priv->backend, transaction->priv->signal_update_detail);
@@ -623,6 +626,26 @@ pk_transaction_repo_signature_required_cb (PkBackend *backend, const gchar *pack
 }
 
 /**
+ * pk_transaction_eula_required_cb:
+ **/
+static void
+pk_transaction_eula_required_cb (PkBackend *backend, const gchar *eula_id, const gchar *package_id,
+				 const gchar *vendor_name, const gchar *license_agreement,
+				 PkTransaction *transaction)
+{
+	g_return_if_fail (PK_IS_TRANSACTION (transaction));
+	g_return_if_fail (transaction->priv->tid != NULL);
+
+	pk_debug ("emitting eula-required %s, %s, %s, %s",
+		  eula_id, package_id, vendor_name, license_agreement);
+	g_signal_emit (transaction, signals [PK_TRANSACTION_EULA_REQUIRED], 0,
+		       eula_id, package_id, vendor_name, license_agreement);
+
+	/* we should mark this transaction so that we finish with a special code */
+	transaction->priv->emit_key_required = TRUE;
+}
+
+/**
  * pk_transaction_require_restart_cb:
  **/
 static void
@@ -757,6 +780,9 @@ pk_transaction_set_running (PkTransaction *transaction)
 	transaction->priv->signal_repo_signature_required =
 		g_signal_connect (transaction->priv->backend, "repo-signature-required",
 				  G_CALLBACK (pk_transaction_repo_signature_required_cb), transaction);
+	transaction->priv->signal_eula_required =
+		g_signal_connect (transaction->priv->backend, "eula-required",
+				  G_CALLBACK (pk_transaction_eula_required_cb), transaction);
 	transaction->priv->signal_require_restart =
 		g_signal_connect (transaction->priv->backend, "require-restart",
 				  G_CALLBACK (pk_transaction_require_restart_cb), transaction);
@@ -2876,6 +2902,11 @@ pk_transaction_class_init (PkTransactionClass *klass)
 			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING_STRING_STRING_STRING_STRING_STRING,
 			      G_TYPE_NONE, 8, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
 			      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+	signals [PK_TRANSACTION_EULA_REQUIRED] =
+		g_signal_new ("eula-required",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL, pk_marshal_VOID__STRING_STRING_STRING_STRING,
+			      G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 	signals [PK_TRANSACTION_REQUIRE_RESTART] =
 		g_signal_new ("require-restart",
 			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
diff --git a/tools/add-error-enum.sh b/tools/add-error-enum.sh
index a643237..5df025f 100755
--- a/tools/add-error-enum.sh
+++ b/tools/add-error-enum.sh
@@ -1,4 +1,4 @@
 #!/bin/sh
 
-$EDITOR docs/spec/pk-introduction.xml libpackagekit/pk-enum.h libpackagekit/pk-enum.c ../gnome-packagekit/src/pk-common-gui.c python/packagekit/backend.py
+$EDITOR docs/spec/pk-introduction.xml libpackagekit/pk-enum.h libpackagekit/pk-enum.c ../gnome-packagekit/libpackagekit-gnome/gpk-common.c python/packagekit/backend.py
 
commit 1d43f6f699fa8b377f22a9e5f24a1ca1f66caa74
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Apr 14 13:35:00 2008 +0100

    don't show the help text when we just got an error

diff --git a/client/pk-console.c b/client/pk-console.c
index 46e269d..224ab66 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -1382,7 +1382,6 @@ out:
 		} else {
 			g_print ("Error:\n  %s\n\n", error->message);
 			g_error_free (error);
-			g_print ("%s", options_help);
 		}
 	}
 
commit 7079e41577ba89c91838cc44cc86b26c47d54b24
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Apr 14 12:24:21 2008 +0100

    fix a few issues with pkcon

diff --git a/client/pk-console.c b/client/pk-console.c
index 3d3b4e2..46e269d 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -954,7 +954,7 @@ pk_console_get_summary (PkRoleEnum roles)
 	/* always */
 	g_string_append_printf (string, "  %s\n", "get-actions");
 	g_string_append_printf (string, "  %s\n", "get-groups");
-	g_string_append_printf (string, "  %s\n", "get-filter");
+	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");
 
@@ -1336,6 +1336,8 @@ main (int argc, char *argv[])
 		g_print ("roles=%s\n", text);
 		g_free (text);
 		maybe_sync = FALSE;
+		/* these can never fail */
+		ret = TRUE;
 
 	} else if (strcmp (mode, "get-filters") == 0) {
 		filters = pk_control_get_filters (control);
@@ -1343,6 +1345,8 @@ main (int argc, char *argv[])
 		g_print ("filters=%s\n", text);
 		g_free (text);
 		maybe_sync = FALSE;
+		/* these can never fail */
+		ret = TRUE;
 
 	} else if (strcmp (mode, "get-groups") == 0) {
 		groups = pk_control_get_groups (control);
@@ -1350,6 +1354,8 @@ main (int argc, char *argv[])
 		g_print ("groups=%s\n", text);
 		g_free (text);
 		maybe_sync = FALSE;
+		/* these can never fail */
+		ret = TRUE;
 
 	} else if (strcmp (mode, "get-transactions") == 0) {
 		ret = pk_client_get_old_transactions (client, 10, &error);
diff --git a/contrib/pk-completion.bash b/contrib/pk-completion.bash
index 2fb3907..ecdf2e2 100755
--- a/contrib/pk-completion.bash
+++ b/contrib/pk-completion.bash
@@ -21,7 +21,7 @@ __pkcon_commandlist="
     get-depends
     get-description
     get-files
-    get-filter
+    get-filters
     get-groups
     get-packages
     get-requires
commit b423d862bce7ff2e3f8cfef53715e180d286c0b1
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Apr 14 12:18:17 2008 +0100

    95packagekit should be executable when installed. fixes rh#442286

diff --git a/data/Makefile.am b/data/Makefile.am
index 65a0200..dcd9c18 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -81,6 +81,9 @@ EXTRA_DIST =						\
 clean-local:
 	rm -f *~
 
+install-data-hook:
+	chmod a+x $(DESTDIR)$(libdir)/pm-utils/sleep.d/95packagekit;
+
 DISTCLEANFILES =					\
 	org.freedesktop.PackageKit.service		\
 	org.freedesktop.PackageKitTestBackend.service	\
commit 873232982b0688412078793a847b3640e738af21
Author: Jens Granseuer <jensgr at gmx.net>
Date:   Mon Apr 14 01:31:31 2008 +0100

    fix compiling PackageKit with GCC2

diff --git a/libpackagekit/pk-debug.h b/libpackagekit/pk-debug.h
index 733dbb9..9344a9c 100644
--- a/libpackagekit/pk-debug.h
+++ b/libpackagekit/pk-debug.h
@@ -54,9 +54,9 @@ G_BEGIN_DECLS
 #define pk_warning(...) pk_warning_real (__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
 #define pk_error(...) pk_error_real (__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
 #else
-#define pk_debug
-#define pk_warning
-#define pk_error
+#define pk_debug(...)
+#define pk_warning(...)
+#define pk_error(...)
 #endif
 
 void		pk_debug_init			(gboolean	 debug);
commit f2b87dcd276963f33da3e5caabf63c7b807bc42f
Author: Richard Hughes <richard at hughsie.com>
Date:   Sun Apr 13 23:41:57 2008 +0100

    rename some commands in pkcon, allow a --filter parameter, and only show entries we can do in the help text

diff --git a/client/pk-console.c b/client/pk-console.c
index 6ba4017..3d3b4e2 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -344,35 +344,6 @@ pk_console_progress_changed_cb (PkClient *client, guint percentage, guint subper
 	}
 }
 
-static const gchar *summary =
-	"PackageKit Console Interface\n"
-	"\n"
-	"Subcommands:\n"
-	"  search name|details|group|file data\n"
-	"  install <package>\n"
-	"  install-file <file>\n"
-	"  install-signature <type> <key_id> <package_id>\n"
-	"  remove <package>\n"
-	"  update <package>\n"
-	"  refresh\n"
-	"  resolve\n"
-	"  update-system\n"
-	"  get updates\n"
-	"  get depends <package>\n"
-	"  get requires <package>\n"
-	"  provides <search>\n"
-	"  get description <package>\n"
-	"  get files <package>\n"
-	"  get updatedetail <package>\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";
-
 /**
  * pk_console_signature_finished_cb:
  **/
@@ -801,241 +772,6 @@ pk_console_get_update_detail (PkClient *client, const gchar *package, GError **e
 }
 
 /**
- * pk_console_process_commands:
- **/
-static gboolean
-pk_console_process_commands (PkClient *client, int argc, char *argv[], GError **error)
-{
-	const gchar *mode;
-	const gchar *value = NULL;
-	const gchar *details = NULL;
-	const gchar *parameter = NULL;
-	PkRoleEnum roles;
-	PkGroupEnum groups;
-	PkFilterEnum filters;
-	gchar *text;
-	gboolean ret = FALSE;
-	gboolean maybe_sync = TRUE;
-
-	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, _("specify a search type"));
-			return FALSE;
-		} else if (strcmp (value, "name") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_client_search_name (client, PK_FILTER_ENUM_NONE, details, error);
-			}
-		} else if (strcmp (value, "details") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_client_search_details (client, PK_FILTER_ENUM_NONE, details, error);
-			}
-		} else if (strcmp (value, "group") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_client_search_group (client, PK_FILTER_ENUM_NONE, details, error);
-			}
-		} else if (strcmp (value, "file") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_client_search_file (client, PK_FILTER_ENUM_NONE, details, error);
-			}
-		} 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, _("specify a package to install"));
-			return FALSE;
-		} else {
-			ret = pk_console_install_package (client, value, error);
-		}
-	} else if (strcmp (mode, "install-signature") == 0) {
-		if (value == NULL || details == NULL || parameter == NULL) {
-			g_set_error (error, 0, 0, _("specify a type, key_id and package_id"));
-			return FALSE;
-		} else {
-			ret = pk_client_install_signature (client, PK_SIGTYPE_ENUM_GPG, details, parameter, error);
-		}
-	} else if (strcmp (mode, "install-file") == 0) {
-		if (value == NULL) {
-			g_set_error (error, 0, 0, _("specify a package to install"));
-			return FALSE;
-		} else {
-			ret = pk_client_install_file (client, value, error);
-		}
-	} else if (strcmp (mode, "remove") == 0) {
-		if (value == NULL) {
-			g_set_error (error, 0, 0, _("specify a package to remove"));
-			return FALSE;
-		} else {
-			ret = pk_console_remove_package (client, value, error);
-		}
-	} else if (strcmp (mode, "update") == 0) {
-		if (value == NULL) {
-			/* do the system update */
-			ret = pk_client_update_system (client, error);
-		} else {
-			ret = pk_console_update_package (client, value, error);
-		}
-	} else if (strcmp (mode, "resolve") == 0) {
-		if (value == NULL) {
-			g_set_error (error, 0, 0, _("specify a package name to resolve"));
-			return FALSE;
-		} else {
-			ret = pk_client_resolve (client, PK_FILTER_ENUM_NONE, value, error);
-		}
-	} else if (strcmp (mode, "enable-repo") == 0) {
-		if (value == NULL) {
-			g_set_error (error, 0, 0, _("specify a repo name"));
-			return FALSE;
-		} else {
-			ret = pk_client_repo_enable (client, value, TRUE, error);
-		}
-	} else if (strcmp (mode, "disable-repo") == 0) {
-		if (value == NULL) {
-			g_set_error (error, 0, 0, _("specify a repo name"));
-			return FALSE;
-		} else {
-			ret = pk_client_repo_enable (client, value, FALSE, error);
-		}
-	} else if (strcmp (mode, "set-repo-data") == 0) {
-		if (value == NULL || details == NULL || parameter == NULL) {
-			g_set_error (error, 0, 0, _("specify a repo name/parameter and value"));
-			return FALSE;
-		} else {
-			ret = pk_client_repo_set_data (client, value, details, parameter, error);
-		}
-	} else if (strcmp (mode, "get") == 0) {
-		if (value == NULL) {
-			g_set_error (error, 0, 0, _("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, _("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, _("specify a correct role"));
-				return FALSE;
-			}
-			ret = pk_control_get_time_since_action (control, role, &time, error);
-			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);
-			maybe_sync = FALSE;
-		} else if (strcmp (value, "depends") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_console_get_depends (client, details, error);
-			}
-		} else if (strcmp (value, "updatedetail") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_console_get_update_detail (client, details, error);
-			}
-		} else if (strcmp (value, "requires") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_console_get_requires (client, details, error);
-			}
-		} else if (strcmp (value, "provides") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a search term"));
-				return FALSE;
-			} else {
-				ret = pk_client_what_provides (client, PK_FILTER_ENUM_NONE, PK_PROVIDES_ENUM_CODEC, details, error);
-			}
-		} else if (strcmp (value, "description") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a package to find the description for"));
-				return FALSE;
-			} else {
-				ret = pk_console_get_description (client, details, error);
-			}
-		} else if (strcmp (value, "files") == 0) {
-			if (details == NULL) {
-				g_set_error (error, 0, 0, _("specify a package to find the files for"));
-				return FALSE;
-			} else {
-				ret = pk_console_get_files (client, details, error);
-			}
-		} else if (strcmp (value, "updates") == 0) {
-			ret = pk_client_get_updates (client, PK_FILTER_ENUM_BASENAME, error);
-		} else if (strcmp (value, "packages") == 0) {
-			ret = pk_client_get_packages (client, PK_FILTER_ENUM_INSTALLED, error);
-		} else if (strcmp (value, "actions") == 0) {
-			roles = pk_control_get_actions (control);
-			text = pk_role_enums_to_text (roles);
-			g_print ("roles=%s", text);
-			g_free (text);
-			maybe_sync = FALSE;
-		} else if (strcmp (value, "filters") == 0) {
-			filters = pk_control_get_filters (control);
-			text = pk_filter_enums_to_text (filters);
-			g_print ("filters=%s", text);
-			g_free (text);
-			maybe_sync = FALSE;
-		} else if (strcmp (value, "repos") == 0) {
-			ret = pk_client_get_repo_list (client, PK_FILTER_ENUM_NONE, error);
-		} else if (strcmp (value, "groups") == 0) {
-			groups = pk_control_get_groups (control);
-			text = pk_group_enums_to_text (groups);
-			g_print ("groups=%s", text);
-			g_free (text);
-			maybe_sync = FALSE;
-		} else if (strcmp (value, "transactions") == 0) {
-			ret = pk_client_get_old_transactions (client, 10, error);
-		} else {
-			g_set_error (error, 0, 0, _("invalid get type"));
-		}
-	} else if (strcmp (mode, "refresh") == 0) {
-		ret = pk_client_refresh_cache (client, FALSE, error);
-	} else {
-		g_set_error (error, 0, 0, _("option not yet supported"));
-	}
-
-	/* do we wait for the method? */
-	if (maybe_sync && !nowait && ret) {
-		g_main_loop_run (loop);
-	}
-
-	return ret;
-}
-
-/**
  * pk_console_error_code_cb:
  **/
 static void
@@ -1204,6 +940,88 @@ pk_console_sigint_handler (int sig)
 }
 
 /**
+ * pk_console_get_summary:
+ **/
+static gchar *
+pk_console_get_summary (PkRoleEnum roles)
+{
+	GString *string;
+	string = g_string_new ("");
+
+	/* header */
+	g_string_append_printf (string, "%s\n\n%s\n", _("PackageKit Console Interface"), _("Subcommands:"));
+
+	/* always */
+	g_string_append_printf (string, "  %s\n", "get-actions");
+	g_string_append_printf (string, "  %s\n", "get-groups");
+	g_string_append_printf (string, "  %s\n", "get-filter");
+	g_string_append_printf (string, "  %s\n", "get-transactions");
+	g_string_append_printf (string, "  %s\n", "get-time");
+
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_SEARCH_NAME) ||
+	    pk_enums_contain (roles, PK_ROLE_ENUM_SEARCH_DETAILS) ||
+	    pk_enums_contain (roles, PK_ROLE_ENUM_SEARCH_GROUP) ||
+	    pk_enums_contain (roles, PK_ROLE_ENUM_SEARCH_FILE)) {
+		g_string_append_printf (string, "  %s\n", "search [name|details|group|file] [data]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_INSTALL_PACKAGE) ||
+	    pk_enums_contain (roles, PK_ROLE_ENUM_INSTALL_FILE)) {
+		g_string_append_printf (string, "  %s\n", "install [package|file]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_INSTALL_SIGNATURE)) {
+		g_string_append_printf (string, "  %s\n", "install-sig [type] [key_id] [package_id]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_REMOVE_PACKAGE)) {
+		g_string_append_printf (string, "  %s\n", "remove [package]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_UPDATE_SYSTEM) ||
+	    pk_enums_contain (roles, PK_ROLE_ENUM_UPDATE_PACKAGES)) {
+		g_string_append_printf (string, "  %s\n", "update <package>");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_REFRESH_CACHE)) {
+		g_string_append_printf (string, "  %s\n", "refresh");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_RESOLVE)) {
+		g_string_append_printf (string, "  %s\n", "resolve [package]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_UPDATES)) {
+		g_string_append_printf (string, "  %s\n", "get-updates");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_DEPENDS)) {
+		g_string_append_printf (string, "  %s\n", "get-depends [package]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_REQUIRES)) {
+		g_string_append_printf (string, "  %s\n", "get-requires [package]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_DESCRIPTION)) {
+		g_string_append_printf (string, "  %s\n", "get-description [package]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_FILES)) {
+		g_string_append_printf (string, "  %s\n", "get-files [package]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_UPDATE_DETAIL)) {
+		g_string_append_printf (string, "  %s\n", "get-update-detail [package]");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_PACKAGES)) {
+		g_string_append_printf (string, "  %s\n", "get-packages");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_GET_REPO_LIST)) {
+		g_string_append_printf (string, "  %s\n", "repo-list");
+	}
+	if (pk_enums_contain (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_enums_contain (roles, PK_ROLE_ENUM_REPO_SET_DATA)) {
+		g_string_append_printf (string, "  %s\n", "repo-set-data [repo_id] [parameter] [value];");
+	}
+	if (pk_enums_contain (roles, PK_ROLE_ENUM_WHAT_PROVIDES)) {
+		g_string_append_printf (string, "  %s\n", "what-provides [search]");
+	}
+	return g_string_free (string, FALSE);
+}
+
+/**
  * main:
  **/
 int
@@ -1216,13 +1034,26 @@ main (int argc, char *argv[])
 	gboolean program_version = FALSE;
 	GOptionContext *context;
 	gchar *options_help;
+	gchar *filter = NULL;
+	gchar *summary;
 	gboolean ret;
+	const gchar *mode;
+	const gchar *value = NULL;
+	const gchar *details = NULL;
+	const gchar *parameter = NULL;
+	PkRoleEnum roles;
+	PkGroupEnum groups;
+	gchar *text;
+	ret = FALSE;
+	gboolean maybe_sync = TRUE;
 
 	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},
+		{ "filter", '\0', 0, G_OPTION_ARG_STRING, &filter,
+			_("Set the filter, e.g. installed"), NULL},
 		{ "nowait", 'n', 0, G_OPTION_ARG_NONE, &nowait,
 			_("Exit without waiting for actions to complete"), NULL},
 		{ NULL}
@@ -1250,6 +1081,11 @@ main (int argc, char *argv[])
 		g_error (_("Could not connect to system DBUS."));
 	}
 
+	/* we need the roles early, as we only show the user only what they can do */
+	control = pk_control_new ();
+	roles = pk_control_get_actions (control);
+	summary = pk_console_get_summary (roles);
+
 	context = g_option_context_new ("PackageKit Console Program");
 	g_option_context_set_summary (context, summary) ;
 	g_option_context_add_main_entries (context, options, NULL);
@@ -1268,7 +1104,6 @@ main (int argc, char *argv[])
 		return 1;
 	}
 
-	pk_debug_init (verbose);
 	loop = g_main_loop_new (NULL, FALSE);
 
 	pconnection = pk_connection_new ();
@@ -1308,19 +1143,237 @@ main (int argc, char *argv[])
 	g_signal_connect (client_signature, "finished",
 			  G_CALLBACK (pk_console_signature_finished_cb), NULL);
 
-	control = pk_control_new ();
-	roles = pk_control_get_actions (control);
+	PkFilterEnum filters = 0;
+	if (filter != NULL) {
+		filters = pk_filter_enums_from_text (filter);
+	}
+
+	mode = argv[1];
+	if (argc > 2) {
+		value = argv[2];
+	}
+	if (argc > 3) {
+		details = argv[3];
+	}
+	if (argc > 4) {
+		parameter = argv[4];
+	}
+
+	/* parse the big list */
+	if (strcmp (mode, "search") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a search type"));
+			goto out;
+
+		} else if (strcmp (value, "name") == 0) {
+			if (details == NULL) {
+				g_print (_("You need to specify a search term"));
+				goto out;
+			}
+			ret = pk_client_search_name (client, filters, details, &error);
+
+		} else if (strcmp (value, "details") == 0) {
+			if (details == NULL) {
+				g_print (_("You need to specify a search term"));
+				goto out;
+			}
+			ret = pk_client_search_details (client, filters, details, &error);
+
+		} else if (strcmp (value, "group") == 0) {
+			if (details == NULL) {
+				g_print (_("You need to specify a search term"));
+				goto out;
+			}
+			ret = pk_client_search_group (client, filters, details, &error);
+
+		} else if (strcmp (value, "file") == 0) {
+			if (details == NULL) {
+				g_print (_("You need to specify a search term"));
+				goto out;
+			}
+			ret = pk_client_search_file (client, filters, details, &error);
+		} else {
+			g_print (_("Invalid search type"));
+		}
+
+	} else if (strcmp (mode, "install") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a package or file to install"));
+			goto out;
+		}
+		/* is it a local file? */
+		ret = g_file_test (value, G_FILE_TEST_EXISTS);
+		if (ret) {
+			ret = pk_client_install_file (client, value, &error);
+		} else {
+			ret = pk_console_install_package (client, value, &error);
+		}
+
+	} else if (strcmp (mode, "install-sig") == 0) {
+		if (value == NULL || details == NULL || parameter == NULL) {
+			g_print (_("You need to specify a type, key_id and package_id"));
+			goto out;
+		}
+		ret = pk_client_install_signature (client, PK_SIGTYPE_ENUM_GPG, details, parameter, &error);
+
+	} else if (strcmp (mode, "remove") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a package to remove"));
+			goto out;
+		}
+		ret = pk_console_remove_package (client, value, &error);
+
+	} else if (strcmp (mode, "update") == 0) {
+		if (value == NULL) {
+			/* do the system update */
+			ret = pk_client_update_system (client, &error);
+		}
+		ret = pk_console_update_package (client, value, &error);
+
+	} else if (strcmp (mode, "resolve") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a package name to resolve"));
+			goto out;
+		}
+		ret = pk_client_resolve (client, filters, value, &error);
+
+	} else if (strcmp (mode, "repo-enable") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a repo name"));
+			goto out;
+		}
+		ret = pk_client_repo_enable (client, value, TRUE, &error);
+
+	} else if (strcmp (mode, "repo-disable") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a repo name"));
+			goto out;
+		}
+		ret = pk_client_repo_enable (client, value, FALSE, &error);
+
+	} else if (strcmp (mode, "repo-set-data") == 0) {
+		if (value == NULL || details == NULL || parameter == NULL) {
+			g_print (_("You need to specify a repo name/parameter and value"));
+			goto out;
+		}
+		ret = pk_client_repo_set_data (client, value, details, parameter, &error);
+
+	} else if (strcmp (mode, "repo-list") == 0) {
+		ret = pk_client_get_repo_list (client, filters, &error);
+
+	} else if (strcmp (mode, "get-time") == 0) {
+		PkRoleEnum role;
+		guint time;
+		gboolean ret;
+		if (value == NULL) {
+			g_print (_("You need to specify a time term"));
+			goto out;
+		}
+		role = pk_role_enum_from_text (value);
+		if (role == PK_ROLE_ENUM_UNKNOWN) {
+			g_print (_("You need to specify a correct role"));
+			goto out;
+		}
+		ret = pk_control_get_time_since_action (control, role, &time, &error);
+		if (ret == FALSE) {
+			g_print (_("Failed to get last time"));
+			goto out;
+		}
+		g_print ("time since %s is %is\n", value, time);
+		maybe_sync = FALSE;
+
+	} else if (strcmp (mode, "get-depends") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a search term"));
+			goto out;
+		}
+		ret = pk_console_get_depends (client, value, &error);
+
+	} else if (strcmp (mode, "get-update-detail") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a search term"));
+			goto out;
+		}
+		ret = pk_console_get_update_detail (client, value, &error);
+
+	} else if (strcmp (mode, "get-requires") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a search term"));
+			goto out;
+		}
+		ret = pk_console_get_requires (client, value, &error);
+
+	} else if (strcmp (mode, "what-provides") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a search term"));
+			goto out;
+		}
+		ret = pk_client_what_provides (client, filters, PK_PROVIDES_ENUM_CODEC, value, &error);
+
+	} else if (strcmp (mode, "get-description") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a package to find the description for"));
+			goto out;
+		}
+		ret = pk_console_get_description (client, value, &error);
 
-	/* run the commands */
-	ret = pk_console_process_commands (client, argc, argv, &error);
+	} else if (strcmp (mode, "get-files") == 0) {
+		if (value == NULL) {
+			g_print (_("You need to specify a package to find the files for"));
+			goto out;
+		}
+		ret = pk_console_get_files (client, value, &error);
+
+	} else if (strcmp (mode, "get-updates") == 0) {
+		ret = pk_client_get_updates (client, filters, &error);
+
+	} else if (strcmp (mode, "get-packages") == 0) {
+		ret = pk_client_get_packages (client, filters, &error);
+
+	} else if (strcmp (mode, "get-actions") == 0) {
+		roles = pk_control_get_actions (control);
+		text = pk_role_enums_to_text (roles);
+		g_print ("roles=%s\n", text);
+		g_free (text);
+		maybe_sync = FALSE;
+
+	} else if (strcmp (mode, "get-filters") == 0) {
+		filters = pk_control_get_filters (control);
+		text = pk_filter_enums_to_text (filters);
+		g_print ("filters=%s\n", text);
+		g_free (text);
+		maybe_sync = FALSE;
+
+	} else if (strcmp (mode, "get-groups") == 0) {
+		groups = pk_control_get_groups (control);
+		text = pk_group_enums_to_text (groups);
+		g_print ("groups=%s\n", text);
+		g_free (text);
+		maybe_sync = FALSE;
+
+	} else if (strcmp (mode, "get-transactions") == 0) {
+		ret = pk_client_get_old_transactions (client, 10, &error);
+
+	} else if (strcmp (mode, "refresh") == 0) {
+		ret = pk_client_refresh_cache (client, FALSE, &error);
+
+	} else {
+		g_print (_("Option '%s' not supported\n"), mode);
+	}
+
+	/* do we wait for the method? */
+	if (maybe_sync && !nowait && ret) {
+		g_main_loop_run (loop);
+	}
+
+out:
 	if (ret == FALSE) {
 		g_print (_("Command failed\n"));
 	}
 	if (error != NULL) {
 		if (g_str_has_prefix (error->message, "org.freedesktop.packagekit."))  {
 			g_print (_("You don't have the necessary privileges for this operation\n"));
-		}
-		else {
+		} else {
 			g_print ("Error:\n  %s\n\n", error->message);
 			g_error_free (error);
 			g_print ("%s", options_help);
@@ -1328,6 +1381,8 @@ main (int argc, char *argv[])
 	}
 
 	g_free (options_help);
+	g_free (filter);
+	g_free (summary);
 	g_object_unref (control);
 	g_object_unref (client);
 	g_object_unref (client_task);
diff --git a/contrib/pk-completion.bash b/contrib/pk-completion.bash
index b4f5f23..2fb3907 100755
--- a/contrib/pk-completion.bash
+++ b/contrib/pk-completion.bash
@@ -17,16 +17,28 @@
 
 
 __pkcon_commandlist="
-    search
+    get-actions
+    get-depends
+    get-description
+    get-files
+    get-filter
+    get-groups
+    get-packages
+    get-requires
+    get-time
+    get-transactions
+    get-update-detail
+    get-updates
     install
-    remove
-    update
     refresh
+    remove
+    repo-disable
+    repo-enable
+    repo-list
+    repo-set-data
     resolve
-    force-refresh
-    get
-    enable-repo
-    disable-repo
+    search
+    update
     "
 
 __pkconcomp ()
@@ -67,40 +79,6 @@ _pkcon_search ()
     return
 }
 
-_pkcon_get ()
-{
-	local i c=1 command
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
-		case "$i" in
-            updates|depends|requires|provides|description|updatedetail|actions|groups|filters|transactions|repos)
-			command="$i"
-			break
-			;;
-		esac
-		c=$((++c))
-	done
-
-	if [ $c -eq $COMP_CWORD -a -z "$command" ]; then
-        __pkconcomp "
-            updates
-            depends
-            requires
-            provides
-            packages
-            description
-            files
-            updatedetail
-            actions
-            groups
-            filters
-            transactions
-            repos
-            "
-    fi
-    return
-}
-
 _pkcon ()
 {
 	local i c=1 command
@@ -119,6 +97,7 @@ _pkcon ()
 		--*=*) COMPREPLY=() ;;
 		--*)   __pkconcomp "
 			--version
+			--filter
 			--verbose
             --help
             --nowait
@@ -132,6 +111,7 @@ _pkcon ()
 			--version
 			--verbose
             --help
+            --filter
             --nowait
             "
             ;;
@@ -142,7 +122,6 @@ _pkcon ()
 
 	case "$command" in
 	search)      _pkcon_search ;;
-	get)         _pkcon_get ;;
 	*)           COMPREPLY=() ;;
 	esac
 }


More information about the PackageKit-commit mailing list