diff options
Diffstat (limited to 'packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch')
-rw-r--r-- | packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch | 2938 |
1 files changed, 2938 insertions, 0 deletions
diff --git a/packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch b/packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch new file mode 100644 index 0000000000..f050a50002 --- /dev/null +++ b/packages/packagekit/files/d1e096c3267c1c9492041382b954e9327bc8bbec.patch @@ -0,0 +1,2938 @@ +diff --git a/backends/alpm/pk-backend-alpm.c b/backends/alpm/pk-backend-alpm.c +index 3270e42..45e7a44 100644 +--- a/backends/alpm/pk-backend-alpm.c ++++ b/backends/alpm/pk-backend-alpm.c +@@ -895,7 +895,7 @@ backend_get_repo_list (PkBackend *backend, PkFilterEnum filters) + static gboolean + backend_install_files_thread (PkBackend *backend) + { +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + gchar **full_paths = pk_backend_get_strv (backend, "full_paths"); + +@@ -1050,7 +1050,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids) + static gboolean + backend_refresh_cache_thread (PkBackend *backend) + { +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + if (alpm_trans_init (PM_TRANS_TYPE_SYNC, PM_TRANS_FLAG_NOSCRIPTLET, cb_trans_evt, cb_trans_conv, cb_trans_progress) != 0) { + pk_backend_error_code (backend, PK_ERROR_ENUM_TRANSACTION_ERROR, alpm_strerror (pm_errno)); +diff --git a/backends/apt/pk-apt-build-db.cpp b/backends/apt/pk-apt-build-db.cpp +index d47c348..885275d 100644 +--- a/backends/apt/pk-apt-build-db.cpp ++++ b/backends/apt/pk-apt-build-db.cpp +@@ -40,7 +40,7 @@ void apt_build_db(PkBackend * backend, sqlite3 *db) + sqlite3_stmt *package = NULL; + + pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates(backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + sdir = g_build_filename(_config->Find("Dir").c_str(),_config->Find("Dir::State").c_str(),_config->Find("Dir::State::lists").c_str(), NULL); + dir = g_dir_open(sdir,0,&error); +diff --git a/backends/apt/pk-sqlite-pkg-cache.cpp b/backends/apt/pk-sqlite-pkg-cache.cpp +index 770fcdf..1bf9a50 100644 +--- a/backends/apt/pk-sqlite-pkg-cache.cpp ++++ b/backends/apt/pk-sqlite-pkg-cache.cpp +@@ -81,7 +81,7 @@ sqlite_search_packages_thread (PkBackend *backend) + const gchar *search; + + pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates(backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + type = pk_backend_get_uint (backend, "type"); + search = pk_backend_get_string (backend, "search"); + +@@ -176,7 +176,7 @@ sqlite_get_details_thread (PkBackend *backend) + } + + pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates(backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + pk_debug("finding %s", pi->name); + +diff --git a/backends/box/pk-backend-box.c b/backends/box/pk-backend-box.c +index b7b8167..9263781 100644 +--- a/backends/box/pk-backend-box.c ++++ b/backends/box/pk-backend-box.c +@@ -138,7 +138,7 @@ backend_find_packages_thread (PkBackend *backend) + filter_box = filter_box | PKG_SEARCH_DETAILS; + } + +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + db = db_open(); + +diff --git a/backends/dummy/pk-backend-dummy.c b/backends/dummy/pk-backend-dummy.c +index 49d4e5a..2df445e 100644 +--- a/backends/dummy/pk-backend-dummy.c ++++ b/backends/dummy/pk-backend-dummy.c +@@ -254,7 +254,7 @@ static void + backend_get_updates (PkBackend *backend, PkFilterEnum filters) + { + pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + /* check network state */ + if (!pk_backend_is_online (backend)) { + pk_backend_error_code (backend, PK_ERROR_ENUM_NO_NETWORK, "Cannot check when offline"); +@@ -268,6 +268,8 @@ static gboolean + backend_install_timeout (gpointer data) + { + PkBackend *backend = (PkBackend *) data; ++ guint sub_percent; ++ + if (_progress_percentage == 100) { + pk_backend_finished (backend); + return FALSE; +@@ -283,9 +285,18 @@ backend_install_timeout (gpointer data) + pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, + "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora", + "Devel files for gtkhtml"); ++ /* this duplicate package should be ignored */ ++ pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, ++ "gtkhtml2-devel;2.19.1-0.fc8;i386;fedora", NULL); + pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL); + } +- _progress_percentage += 10; ++ if (_progress_percentage > 30 && _progress_percentage < 50) { ++ sub_percent = ((gfloat) (_progress_percentage - 30.0f) / 20.0f) * 100.0f; ++ pk_backend_set_sub_percentage (backend, sub_percent); ++ } else { ++ pk_backend_set_sub_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); ++ } ++ _progress_percentage += 1; + pk_backend_set_percentage (backend, _progress_percentage); + return TRUE; + } +@@ -348,7 +359,7 @@ backend_install_packages (PkBackend *backend, gchar **package_ids) + pk_backend_package (backend, PK_INFO_ENUM_DOWNLOADING, + "gtkhtml2;2.19.1-4.fc8;i386;fedora", + "An HTML widget for GTK+ 2.0"); +- _signal_timeout = g_timeout_add (1000, backend_install_timeout, backend); ++ _signal_timeout = g_timeout_add (100, backend_install_timeout, backend); + } + + /** +@@ -526,7 +537,7 @@ backend_search_name_timeout (gpointer data) + static void + backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search) + { +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + pk_backend_set_allow_cancel (backend, TRUE); + pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); + _signal_timeout = g_timeout_add (2000, backend_search_name_timeout, backend); +diff --git a/backends/opkg/pk-backend-opkg.c b/backends/opkg/pk-backend-opkg.c +index ecc97be..7649bab 100644 +--- a/backends/opkg/pk-backend-opkg.c ++++ b/backends/opkg/pk-backend-opkg.c +@@ -155,6 +155,38 @@ pk_opkg_progress_cb (opkg_t *opkg, const opkg_progress_data_t *pdata, void *data + return; + + pk_backend_set_percentage (backend, pdata->percentage); ++ if (pdata->package) ++ { ++ gchar *uid; ++ opkg_package_t *pkg = pdata->package; ++ gint status = PK_INFO_ENUM_UNKNOWN; ++ ++ uid = g_strdup_printf ("%s;%s;%s;", ++ pkg->name, pkg->version, pkg->architecture); ++ ++ if (pdata->action == OPKG_DOWNLOAD) ++ status = PK_INFO_ENUM_DOWNLOADING; ++ else if (pdata->action == OPKG_INSTALL) ++ status = PK_INFO_ENUM_INSTALLING; ++ else if (pdata->action == OPKG_REMOVE) ++ status = PK_INFO_ENUM_REMOVING; ++ ++ pk_backend_package (backend, status, uid, pkg->description); ++ g_free (uid); ++ } ++ ++ switch (pdata->action) ++ { ++ case OPKG_DOWNLOAD: ++ pk_backend_set_status (backend, PK_STATUS_ENUM_DOWNLOAD); ++ break; ++ case OPKG_INSTALL: ++ pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL); ++ break; ++ case OPKG_REMOVE: ++ pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE); ++ break; ++ } + } + + static gboolean +@@ -163,8 +195,12 @@ backend_refresh_cache_thread (PkBackend *backend) + int ret; + + ret = opkg_update_package_lists (opkg, pk_opkg_progress_cb, backend); ++ + if (ret) { +- opkg_unknown_error (backend, ret, "Refreshing cache"); ++ if (ret == OPKG_DOWNLOAD_FAILED) ++ pk_backend_error_code (backend, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, NULL); ++ else ++ opkg_unknown_error (backend, ret, "Refreshing cache"); + } + pk_backend_finished (backend); + +@@ -178,7 +214,7 @@ static void + backend_refresh_cache (PkBackend *backend, gboolean force) + { + pk_backend_set_status (backend, PK_STATUS_ENUM_REFRESH_CACHE); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + + pk_backend_thread_create (backend, backend_refresh_cache_thread); +@@ -279,7 +315,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear + + + pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + params = g_new0 (SearchParams, 1); + params->filters = filters; +@@ -301,7 +337,7 @@ backend_search_description (PkBackend *backend, PkFilterEnum filters, const gcha + + + pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + params = g_new0 (SearchParams, 1); + params->filters = filters; +@@ -320,7 +356,7 @@ backend_search_group (PkBackend *backend, PkFilterEnum filters, const gchar *sea + + + pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + params = g_new0 (SearchParams, 1); + params->filters = filters; +@@ -337,30 +373,52 @@ static gboolean + backend_install_packages_thread (PkBackend *backend) + { + PkPackageId *pi; +- gint err; +- const gchar *package_id; ++ gint err, i; ++ gchar **package_ids; + +- package_id = pk_backend_get_string (backend, "pkid"); +- pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_id, NULL); ++ package_ids = pk_backend_get_strv (backend, "pkids"); + +- pi = pk_package_id_new_from_string (package_id); ++ err = 0; ++ ++ for (i = 0; package_ids[i]; i++) ++ { ++ pk_backend_package (backend, PK_INFO_ENUM_INSTALLING, package_ids[0], NULL); + +- err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend); +- if (err != 0) +- opkg_unknown_error (backend, err, "Install"); ++ pi = pk_package_id_new_from_string (package_ids[0]); ++ ++ err = opkg_install_package (opkg, pi->name, pk_opkg_progress_cb, backend); ++ switch (err) ++ { ++ case OPKG_NO_ERROR: ++ break; ++ case OPKG_DEPENDANCIES_FAILED: ++ pk_backend_error_code (backend, PK_ERROR_ENUM_DEP_RESOLUTION_FAILED, NULL); ++ break; ++ case OPKG_PACKAGE_ALREADY_INSTALLED: ++ pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ALREADY_INSTALLED, NULL); ++ break; ++ case OPKG_PACKAGE_NOT_AVAILABLE: ++ pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL); ++ break; ++ default: ++ opkg_unknown_error (backend, err, "Install"); ++ } ++ pk_package_id_free (pi); ++ if (err != 0) ++ break; ++ } + +- pk_package_id_free (pi); + pk_backend_finished (backend); + return (err == 0); + } + + static void +-backend_install_packages (PkBackend *backend, gchar **package_id) ++backend_install_packages (PkBackend *backend, gchar **package_ids) + { +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + pk_backend_set_status (backend, PK_STATUS_ENUM_INSTALL); + +- pk_backend_set_string (backend, "pkid", package_id[0]); ++ pk_backend_set_strv (backend, "pkids", package_ids); + + pk_backend_thread_create (backend, backend_install_packages_thread); + } +@@ -369,7 +427,7 @@ static gboolean + backend_remove_packages_thread (PkBackend *backend) + { + PkPackageId *pi; +- gint err; ++ gint err, i; + gchar **package_ids; + gboolean allow_deps; + gboolean autoremove; +@@ -382,19 +440,34 @@ backend_remove_packages_thread (PkBackend *backend) + autoremove = GPOINTER_TO_INT (data[2]); + g_free (data); + +- pi = pk_package_id_new_from_string (package_ids[0]); +- pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL); +- + opkg_set_option (opkg, "autoremove", &autoremove); + opkg_set_option (opkg, "force_removal_of_dependent_packages", &allow_deps); + +- err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend); ++ err = 0; + +- /* TODO: improve error reporting */ +- if (err != 0) +- opkg_unknown_error (backend, err, "Remove"); ++ for (i = 0; package_ids[i]; i++) ++ { ++ pi = pk_package_id_new_from_string (package_ids[0]); ++ pk_backend_package (backend, PK_INFO_ENUM_REMOVING, package_ids[0], NULL); ++ ++ err = opkg_remove_package (opkg, pi->name, pk_opkg_progress_cb, backend); ++ ++ switch (err) ++ { ++ case OPKG_NO_ERROR: ++ break; ++ case OPKG_PACKAGE_NOT_INSTALLED: ++ pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL); ++ break; ++ default: ++ opkg_unknown_error (backend, err, "Remove"); ++ } ++ pk_package_id_free (pi); ++ ++ if (err != 0) ++ break; ++ } + +- pk_package_id_free (pi); + pk_backend_finished (backend); + return (err == 0); + } +@@ -405,7 +478,7 @@ backend_remove_packages (PkBackend *backend, gchar **package_ids, gboolean allow + gpointer *params; + + pk_backend_set_status (backend, PK_STATUS_ENUM_REMOVE); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + /* params is a small array we can pack our thread parameters into */ + params = g_new0 (gpointer, 2); +@@ -450,7 +523,7 @@ static void + backend_update_system (PkBackend *backend) + { + pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + pk_backend_thread_create (backend, backend_update_system_thread); + } +@@ -478,8 +551,14 @@ backend_update_package_thread (PkBackend *backend) + } + + err = opkg_upgrade_package (opkg, pi->name, pk_opkg_progress_cb, backend); +- +- if (err != 0) { ++ switch (err) ++ { ++ case OPKG_NO_ERROR: ++ break; ++ case OPKG_PACKAGE_NOT_INSTALLED: ++ pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_INSTALLED, NULL); ++ break; ++ default: + opkg_unknown_error (backend, err, "Update package"); + } + +@@ -494,7 +573,7 @@ backend_update_packages (PkBackend *backend, gchar **package_ids) + gint i; + + pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + for (i = 0; package_ids[i]; i++) { + pk_backend_set_string (backend, "pkgid", package_ids[i]); +@@ -536,7 +615,7 @@ static void + backend_get_updates (PkBackend *backend, PkFilterEnum filters) + { + pk_backend_set_status (backend, PK_STATUS_ENUM_UPDATE); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + pk_backend_thread_create (backend, backend_get_updates_thread); + } +@@ -572,19 +651,26 @@ backend_get_details_thread (PkBackend *backend) + if (pi == NULL) + { + pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id"); +- pk_package_id_free (pi); ++ pk_backend_finished (backend); + return FALSE; + } + + + pkg = opkg_find_package (opkg, pi->name, pi->version, pi->arch, pi->data); ++ pk_package_id_free (pi); ++ ++ if (!pkg) ++ { ++ pk_backend_error_code (backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, NULL); ++ pk_backend_finished (backend); ++ return FALSE; ++ } + + newid = g_strdup_printf ("%s;%s;%s;%s", pkg->name, pkg->version, pkg->architecture, pkg->repository); + + pk_backend_details (backend, newid, NULL, 0, pkg->description, pkg->url, pkg->size); + + g_free (newid); +- pk_package_id_free (pi); + pk_backend_finished (backend); + return TRUE; + } +@@ -592,7 +678,7 @@ backend_get_details_thread (PkBackend *backend) + static void + backend_get_details (PkBackend *backend, const gchar *package_id) + { +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + pk_backend_thread_create (backend, backend_get_details_thread); + } + +diff --git a/backends/test/pk-backend-test-dbus.c b/backends/test/pk-backend-test-dbus.c +index 5dfea32..76686dc 100644 +--- a/backends/test/pk-backend-test-dbus.c ++++ b/backends/test/pk-backend-test-dbus.c +@@ -36,7 +36,7 @@ static void + backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search) + { + pk_backend_set_allow_cancel (backend, TRUE); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + pk_backend_dbus_search_name (dbus, filters, search); + } + +diff --git a/backends/test/pk-backend-test-spawn.c b/backends/test/pk-backend-test-spawn.c +index 2958c05..584f44c 100644 +--- a/backends/test/pk-backend-test-spawn.c ++++ b/backends/test/pk-backend-test-spawn.c +@@ -35,7 +35,7 @@ backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *sear + { + gchar *filters_text; + pk_backend_set_allow_cancel (backend, TRUE); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + filters_text = pk_filter_enums_to_text (filters); + pk_backend_spawn_helper (spawn, "search-name.sh", filters_text, search, NULL); + g_free (filters_text); +diff --git a/backends/test/pk-backend-test-succeed.c b/backends/test/pk-backend-test-succeed.c +index 17cdc6e..c046c1d 100644 +--- a/backends/test/pk-backend-test-succeed.c ++++ b/backends/test/pk-backend-test-succeed.c +@@ -236,7 +236,7 @@ backend_search_name_timeout (gpointer data) + static void + backend_search_name (PkBackend *backend, PkFilterEnum filters, const gchar *search) + { +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + g_timeout_add (200000, backend_search_name_timeout, backend); + } + +diff --git a/backends/yum/helpers/yumBackend.py b/backends/yum/helpers/yumBackend.py +index f76e27c..5b2da8f 100644 +--- a/backends/yum/helpers/yumBackend.py ++++ b/backends/yum/helpers/yumBackend.py +@@ -801,6 +801,8 @@ class PackageKitYumBackend(PackageKitBaseBackend): + old_throttle = self.yumbase.conf.throttle + self.yumbase.conf.throttle = "60%" # Set bandwidth throttle to 60% + # to avoid taking all the system's bandwidth. ++ old_skip_broken = self.yumbase.conf.skip_broken ++ self.yumbase.conf.skip_broken = 1 + + try: + txmbr = self.yumbase.update() # Add all updates to Transaction +@@ -812,6 +814,7 @@ class PackageKitYumBackend(PackageKitBaseBackend): + self.error(ERROR_NO_PACKAGES_TO_UPDATE,"Nothing to do") + + self.yumbase.conf.throttle = old_throttle ++ self.yumbase.conf.skip_broken = old_skip_broken + + def refresh_cache(self): + ''' +@@ -905,7 +908,7 @@ class PackageKitYumBackend(PackageKitBaseBackend): + if txmbrs: + self._runYumTransaction() + else: +- self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"This package could not be installed as it is already installed") ++ self.error(ERROR_PACKAGE_ALREADY_INSTALLED,"The package is already installed") + + def _checkForNewer(self,po): + pkgs = self.yumbase.pkgSack.returnNewestByName(name=po.name) +@@ -1003,7 +1006,7 @@ class PackageKitYumBackend(PackageKitBaseBackend): + return False + + if self._is_inst(po): +- self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "%s is already installed" % str(po)) ++ self.error(ERROR_PACKAGE_ALREADY_INSTALLED, "The package %s is already installed" % str(po)) + return False + + if len(self.yumbase.conf.exclude) > 0: +diff --git a/backends/yum2/helpers/testyum2.py b/backends/yum2/helpers/testyum2.py +index cdec507..85b47f9 100755 +--- a/backends/yum2/helpers/testyum2.py ++++ b/backends/yum2/helpers/testyum2.py +@@ -80,7 +80,7 @@ try: + #iface.GetPackages(FILTER_INSTALLED,'no') + if cmd == 'get-repolist' or cmd == 'all': + print "Testing GetRepoList()" +- iface.GetRepoList() ++ iface.GetRepoList("") + if cmd == 'get-updatedetail' or cmd == 'all': + print "Testing GetUpdateDetail(PKG_ID)" + iface.GetUpdateDetail(PKG_ID) +diff --git a/backends/yum2/helpers/yumDBUSBackend.py b/backends/yum2/helpers/yumDBUSBackend.py +index 9cfed94..29f5b03 100755 +--- a/backends/yum2/helpers/yumDBUSBackend.py ++++ b/backends/yum2/helpers/yumDBUSBackend.py +@@ -434,7 +434,7 @@ class PackageKitYumBackend(PackageKitBaseBackend): + try: + pkgGroupDict = self._buildGroupDict() + fltlist = filters.split(';') +- found = {} ++ installed_nevra = [] # yum returns packages as available even when installed + + if not FILTER_NOT_INSTALLED in fltlist: + # Check installed for group +@@ -450,21 +450,31 @@ class PackageKitYumBackend(PackageKitBaseBackend): + group = groupMap[cg] # use the pk group name, instead of yum 'category/group' + if group == key: + if self._do_extra_filtering(pkg, fltlist): +- self._show_package(pkg, INFO_INSTALLED) ++ package_list.append((pkg,INFO_INSTALLED)) ++ installed_nevra.append(self._get_nevra(pkg)) ++ + if not FILTER_INSTALLED in fltlist: + # Check available for group + for pkg in self.yumbase.pkgSack: + if self._cancel_check("Search cancelled."): + # _cancel_check() sets the error message, unlocks yum, and calls Finished() + return +- group = GROUP_OTHER +- if pkgGroupDict.has_key(pkg.name): +- cg = pkgGroupDict[pkg.name] +- if groupMap.has_key(cg): +- group = groupMap[cg] +- if group == key: +- if self._do_extra_filtering(pkg, fltlist): +- self._show_package(pkg, INFO_AVAILABLE) ++ ++ nevra = self._get_nevra(pkg) ++ if nevra not in installed_nevra: ++ group = GROUP_OTHER ++ if pkgGroupDict.has_key(pkg.name): ++ cg = pkgGroupDict[pkg.name] ++ if groupMap.has_key(cg): ++ group = groupMap[cg] ++ if group == key: ++ if self._do_extra_filtering(pkg, fltlist): ++ package_list.append((pkg,INFO_AVAILABLE)) ++ ++ except yum.Errors.GroupsError,e: ++ self._unlock_yum() ++ self.ErrorCode(ERROR_GROUP_NOT_FOUND, str(e)) ++ self.Finished(EXIT_FAILED) + except yum.Errors.RepoError,e: + self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.") + self._refresh_yum_cache() +@@ -473,6 +483,14 @@ class PackageKitYumBackend(PackageKitBaseBackend): + + return + ++ # basename filter if specified ++ if FILTER_BASENAME in fltlist: ++ for (pkg,status) in self._basename_filter(package_list): ++ self._show_package(pkg,status) ++ else: ++ for (pkg,status) in package_list: ++ self._show_package(pkg,status) ++ + self._unlock_yum() + self.Finished(EXIT_SUCCESS) + +@@ -724,6 +742,11 @@ class PackageKitYumBackend(PackageKitBaseBackend): + #we might have a rounding error + self.PercentageChanged(100) + ++ except yum.Errors.RepoError,e: ++ self._unlock_yum() ++ self.ErrorCode(ERROR_REPO_CONFIGURATION_ERROR,str(e)) ++ self.Finished(EXIT_FAILED) ++ self.Exit() + except yum.Errors.YumBaseError, e: + self._unlock_yum() + # This should be a better-defined error, but I'm not sure +@@ -837,6 +860,7 @@ class PackageKitYumBackend(PackageKitBaseBackend): + Needed to be implemented in a sub class + ''' + if inst_file.endswith('.src.rpm'): ++ self._unlock_yum() + self.ErrorCode(ERROR_CANNOT_INSTALL_SOURCE_PACKAGE,'Backend will not install a src rpm file') + self.Finished(EXIT_FAILED) + return +@@ -1385,30 +1409,30 @@ class PackageKitYumBackend(PackageKitBaseBackend): + res = self.yumbase.searchGenerator(searchlist, [key]) + fltlist = filters.split(';') + +- available = [] +- count = 1 ++ seen_nevra = [] # yum returns packages as available even when installed ++ pkg_list = [] # only do the second iteration on not installed pkgs ++ package_list = [] #we can't do emitting as found if we are post-processing ++ + for (pkg,values) in res: + if self._cancel_check("Search cancelled."): + return False + # are we installed? + if pkg.repo.id == 'installed': +- if FILTER_NOT_INSTALLED not in fltlist: +- if self._do_extra_filtering(pkg,fltlist): +- count+=1 +- if count > 100: +- break +- self._show_package(pkg, INFO_INSTALLED) ++ if self._do_extra_filtering(pkg,fltlist): ++ package_list.append((pkg,INFO_INSTALLED)) ++ seen_nevra.append(self._get_nevra(pkg)) + else: +- available.append(pkg) ++ pkg_list.append(pkg) + +- # Now show available packages. +- if FILTER_INSTALLED not in fltlist: +- for pkg in available: +- if self._cancel_check("Search cancelled."): +- return False +- if self._do_extra_filtering(pkg,fltlist): +- self._show_package(pkg, INFO_AVAILABLE) ++ for pkg in pkg_list: ++ if self._cancel_check("Search cancelled."): ++ return False + ++ nevra = self._get_nevra(pkg) ++ if nevra not in seen_nevra: ++ if self._do_extra_filtering(pkg,fltlist): ++ package_list.append((pkg,INFO_AVAILABLE)) ++ seen_nevra.append(self._get_nevra(pkg)) + except yum.Errors.RepoError,e: + self.Message(MESSAGE_NOTICE, "The package cache is invalid and is being rebuilt.") + self._refresh_yum_cache() +@@ -1417,13 +1441,22 @@ class PackageKitYumBackend(PackageKitBaseBackend): + + return False + ++ # basename filter if specified ++ if FILTER_BASENAME in fltlist: ++ for (pkg,status) in self._basename_filter(package_list): ++ self._show_package(pkg,status) ++ else: ++ for (pkg,status) in package_list: ++ self._show_package(pkg,status) ++ + return True + + def _do_extra_filtering(self,pkg,filterList): + ''' do extra filtering (gui,devel etc) ''' + for filter in filterList: + if filter in (FILTER_INSTALLED, FILTER_NOT_INSTALLED): +- continue ++ if not self._do_installed_filtering(filter,pkg): ++ return False + elif filter in (FILTER_GUI, FILTER_NOT_GUI): + if not self._do_gui_filtering(filter, pkg): + return False +@@ -1433,11 +1466,17 @@ class PackageKitYumBackend(PackageKitBaseBackend): + elif filter in (FILTER_FREE, FILTER_NOT_FREE): + if not self._do_free_filtering(filter, pkg): + return False +- elif filter in (FILTER_BASENAME, FILTER_NOT_BASENAME): +- if not self._do_basename_filtering(filter, pkg): +- return False + return True + ++ def _do_installed_filtering(self,flt,pkg): ++ isInstalled = False ++ if flt == FILTER_INSTALLED: ++ wantInstalled = True ++ else: ++ wantInstalled = False ++ isInstalled = pkg.repo.id == 'installed' ++ return isInstalled == wantInstalled ++ + def _do_gui_filtering(self,flt,pkg): + isGUI = False + if flt == FILTER_GUI: +@@ -1477,32 +1516,7 @@ class PackageKitYumBackend(PackageKitBaseBackend): + + return isFree == wantFree + +- def _do_basename_filtering(self,flt,pkg): +- if flt == FILTER_BASENAME: +- wantBase = True +- else: +- wantBase = False +- +- isBase = self._check_basename(pkg) +- +- return isBase == wantBase + +- def _check_basename(self, pkg): +- ''' +- If a package does not have a source rpm (If that ever +- happens), or it does have a source RPM, and the package's name +- is the same as the source RPM's name, then we assume it is the +- 'base' package. +- ''' +- basename = pkg.name +- +- if pkg.sourcerpm: +- basename = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0] +- +- if basename == pkg.name: +- return True +- +- return False + + def _is_development_repo(self, repo): + if repo.endswith('-debuginfo'): +@@ -1576,28 +1590,41 @@ class PackageKitYumBackend(PackageKitBaseBackend): + ''' + find a package based on a package id (name;version;arch;repoid) + ''' +- # Split up the id +- (n,idver,a,d) = self.get_package_from_id(id) +- # get e,v,r from package id version +- e,v,r = self._getEVR(idver) ++ # is this an real id or just an name ++ if len(id.split(';')) > 1: ++ # Split up the id ++ (n,idver,a,d) = self.get_package_from_id(id) ++ # get e,v,r from package id version ++ e,v,r = self._getEVR(idver) ++ else: ++ n = id ++ e = v = r = a = None + # search the rpmdb for the nevra + pkgs = self.yumbase.rpmdb.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a) +- # if the package is found, then return it ++ # if the package is found, then return it (do not have to match the repo_id) + if len(pkgs) != 0: + return pkgs[0],True + # search the pkgSack for the nevra +- pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a) +- # if the package is found, then return it +- if len(pkgs) != 0: +- return pkgs[0],False +- else: ++ try: ++ pkgs = self.yumbase.pkgSack.searchNevra(name=n,epoch=e,ver=v,rel=r,arch=a) ++ except yum.Errors.RepoError,e: ++ self.error(ERROR_REPO_NOT_AVAILABLE,str(e)) ++ # nothing found ++ if len(pkgs) == 0: + return None,False ++ # one NEVRA in a single repo ++ if len(pkgs) == 1: ++ return pkgs[0],False ++ # we might have the same NEVRA in multiple repos, match by repo name ++ for pkg in pkgs: ++ if d == pkg.repoid: ++ return pkg,False ++ # repo id did not match ++ return None,False + + def _is_inst(self,pkg): + return self.yumbase.rpmdb.installed(po=pkg) + +- +- + def _installable(self, pkg, ematch=False): + + """check if the package is reasonably installable, true/false""" +@@ -1764,6 +1791,57 @@ class PackageKitYumBackend(PackageKitBaseBackend): + return INFO_ENHANCEMENT + else: + return INFO_UNKNOWN ++ def _is_main_package(self,repo): ++ if repo.endswith('-debuginfo'): ++ return False ++ if repo.endswith('-devel'): ++ return False ++ if repo.endswith('-libs'): ++ return False ++ return True ++ ++ def _basename_filter(self,package_list): ++ ''' ++ Filter the list so that the number of packages are reduced. ++ This is done by only displaying gtk2 rather than gtk2-devel, gtk2-debuginfo, etc. ++ This imlementation is done by comparing the SRPM name, and if not falling back ++ to the first entry. ++ We have to fall back else we don't emit packages where the SRPM does not produce a ++ RPM with the same name, for instance, mono produces mono-core, mono-data and mono-winforms. ++ @package_list: a (pkg,status) list of packages ++ A new list is returned that has been filtered ++ ''' ++ base_list = [] ++ output_list = [] ++ base_list_already_got = [] ++ ++ #find out the srpm name and add to a new array of compound data ++ for (pkg,status) in package_list: ++ if pkg.sourcerpm: ++ base = rpmUtils.miscutils.splitFilename(pkg.sourcerpm)[0] ++ base_list.append ((pkg,status,base,pkg.version)); ++ else: ++ base_list.append ((pkg,status,'nosrpm',pkg.version)); ++ ++ #find all the packages that match thier basename name (done seporately so we get the "best" match) ++ for (pkg,status,base,version) in base_list: ++ if base == pkg.name and (base,version) not in base_list_already_got: ++ output_list.append((pkg,status)) ++ base_list_already_got.append ((base,version)) ++ ++ #for all the ones not yet got, can we match against a non devel match? ++ for (pkg,status,base,version) in base_list: ++ if (base,version) not in base_list_already_got: ++ if self._is_main_package(pkg.name): ++ output_list.append((pkg,status)) ++ base_list_already_got.append ((base,version)) ++ ++ #add the remainder of the packages, which should just be the single debuginfo's ++ for (pkg,status,base,version) in base_list: ++ if (base,version) not in base_list_already_got: ++ output_list.append((pkg,status)) ++ base_list_already_got.append ((base,version)) ++ return output_list + + def _get_obsoleted(self,name): + obsoletes = self.yumbase.up.getObsoletesTuples( newest=1 ) +diff --git a/backends/zypp/pk-backend-zypp.cpp b/backends/zypp/pk-backend-zypp.cpp +index 746da82..15c4b4f 100644 +--- a/backends/zypp/pk-backend-zypp.cpp ++++ b/backends/zypp/pk-backend-zypp.cpp +@@ -1170,7 +1170,7 @@ backend_find_packages_thread (PkBackend *backend) + mode = pk_backend_get_uint (backend, "mode"); + + pk_backend_set_status (backend, PK_STATUS_ENUM_QUERY); +- pk_backend_no_percentage_updates (backend); ++ pk_backend_set_percentage (backend, PK_BACKEND_PERCENTAGE_INVALID); + + std::vector<zypp::sat::Solvable> *v = new std::vector<zypp::sat::Solvable>; + std::vector<zypp::sat::Solvable> *v2 = new std::vector<zypp::sat::Solvable>; +diff --git a/client/pk-console.c b/client/pk-console.c +index 8f69068..5a05a8e 100644 +--- a/client/pk-console.c ++++ b/client/pk-console.c +@@ -50,7 +50,7 @@ static gboolean awaiting_space = FALSE; + static gboolean trusted = TRUE; + static guint timer_id = 0; + static guint percentage_last = 0; +-static gchar *filename = NULL; ++static gchar **files_cache = NULL; + static PkControl *control = NULL; + static PkClient *client = NULL; + static PkClient *client_task = NULL; +@@ -494,6 +494,12 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar * + return g_strdup (package); + } + ++ ret = pk_client_reset (client_task, error); ++ if (ret == FALSE) { ++ pk_warning ("failed to reset client task"); ++ return NULL; ++ } ++ + /* we need to resolve it */ + ret = pk_client_resolve (client_task, filter, package, error); + if (ret == FALSE) { +@@ -549,20 +555,93 @@ pk_console_perhaps_resolve (PkClient *client, PkFilterEnum filter, const gchar * + } + + /** +- * pk_console_install_package: ++ * pk_console_install_stuff: + **/ + static gboolean +-pk_console_install_package (PkClient *client, const gchar *package, GError **error) ++pk_console_install_stuff (PkClient *client, gchar **packages, GError **error) + { +- gboolean ret; +- gchar *package_id; +- package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, package, error); +- if (package_id == NULL) { +- g_print ("%s\n", _("Could not find a package with that name to install, or package already installed")); +- return FALSE; ++ gboolean ret = TRUE; ++ gboolean is_local; ++ gchar *package_id = NULL; ++ gchar **package_ids = NULL; ++ gchar **files = NULL; ++ guint i; ++ guint length; ++ GPtrArray *array_packages; ++ GPtrArray *array_files; ++ ++ array_packages = g_ptr_array_new (); ++ array_files = g_ptr_array_new (); ++ length = g_strv_length (packages); ++ for (i=2; i<length; i++) { ++ is_local = g_file_test (packages[i], G_FILE_TEST_EXISTS); ++ if (is_local) { ++ g_ptr_array_add (array_files, g_strdup (packages[i])); ++ } else { ++ package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_NOT_INSTALLED, packages[i], error); ++ if (package_id == NULL) { ++ g_print ("%s\n", _("Could not find a package with that name to install, or package already installed")); ++ ret = FALSE; ++ break; ++ } ++ g_ptr_array_add (array_packages, package_id); ++ } + } +- ret = pk_client_install_package (client, package_id, error); +- g_free (package_id); ++ ++ /* one of the resolves failed */ ++ if (!ret) { ++ pk_warning ("resolve failed"); ++ goto out; ++ } ++ ++ ++ /* any to process? */ ++ if (array_packages->len > 0) { ++ /* convert to strv */ ++ package_ids = pk_ptr_array_to_argv (array_packages); ++ ++ /* reset */ ++ ret = pk_client_reset (client, error); ++ if (!ret) { ++ pk_warning ("failed to reset"); ++ goto out; ++ } ++ ++ ret = pk_client_install_package (client, package_id, error); ++ if (!ret) { ++ pk_warning ("failed to install packages"); ++ goto out; ++ } ++ } ++ ++ /* any to process? */ ++ if (array_files->len > 0) { ++ /* convert to strv */ ++ files = pk_ptr_array_to_argv (array_files); ++ ++ /* save for untrusted callback */ ++ g_strfreev (files_cache); ++ files_cache = g_strdupv (files); ++ ++ /* reset */ ++ ret = pk_client_reset (client, error); ++ if (!ret) { ++ pk_warning ("failed to reset"); ++ goto out; ++ } ++ ++ ret = pk_client_install_files (client, trusted, files, error); ++ if (!ret) { ++ pk_warning ("failed to install files"); ++ goto out; ++ } ++ } ++ ++out: ++ g_strfreev (package_ids); ++ g_strfreev (files); ++ g_ptr_array_free (array_files, TRUE); ++ g_ptr_array_free (array_packages, TRUE); + return ret; + } + +@@ -570,16 +649,16 @@ pk_console_install_package (PkClient *client, const gchar *package, GError **err + * pk_console_remove_only: + **/ + static gboolean +-pk_console_remove_only (PkClient *client, const gchar *package_id, gboolean force, gboolean autoremove, GError **error) ++pk_console_remove_only (PkClient *client, gchar **package_ids, gboolean force, GError **error) + { + gboolean ret; + +- pk_debug ("remove %s", package_id); ++ pk_debug ("remove+ %s", package_ids[0]); + ret = pk_client_reset (client, error); + if (!ret) { + return ret; + } +- return pk_client_remove_package (client, package_id, force, autoremove, error); ++ return pk_client_remove_packages (client, package_ids, force, FALSE, error); + } + + /** +@@ -625,64 +704,99 @@ pk_console_get_prompt (const gchar *question, gboolean defaultyes) + } + + /** +- * pk_console_remove_package: ++ * pk_console_remove_packages: + **/ + static gboolean +-pk_console_remove_package (PkClient *client, const gchar *package, GError **error) ++pk_console_remove_packages (PkClient *client, gchar **packages, GError **error) + { + gchar *package_id; +- gboolean ret; +- guint length; ++ gboolean ret = TRUE; + PkPackageItem *item; + PkPackageId *ident; +- guint i; ++ guint i, j; ++ guint size; ++ guint length; + gboolean remove; ++ GPtrArray *array; ++ gchar **package_ids = NULL; ++ PkPackageList *list; ++ ++ array = g_ptr_array_new (); ++ list = pk_package_list_new (); ++ length = g_strv_length (packages); ++ for (i=2; i<length; i++) { ++ package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, packages[i], error); ++ if (package_id == NULL) { ++ g_print ("%s:%s\n", _("Could not find a package to remove"), packages[i]); ++ ret = FALSE; ++ break; ++ } ++ g_ptr_array_add (array, g_strdup (package_id)); ++ pk_debug ("resolved to %s", package_id); ++ g_free (package_id); ++ } + +- package_id = pk_console_perhaps_resolve (client, PK_FILTER_ENUM_INSTALLED, package, error); +- if (package_id == NULL) { +- g_print ("%s\n", _("Could not find a package with that name to remove")); +- return FALSE; ++ /* one of the resolves failed */ ++ if (!ret) { ++ goto out; + } + ++ /* convert to strv */ ++ package_ids = pk_ptr_array_to_argv (array); ++ + /* are we dumb and can't check for requires? */ + if (!pk_enums_contain (roles, PK_ROLE_ENUM_GET_REQUIRES)) { + /* no, just try to remove it without deps */ +- ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error); +- g_free (package_id); +- return ret; ++ ret = pk_console_remove_only (client, package_ids, FALSE, error); ++ goto out; + } + +- /* see if any packages require this one */ +- ret = pk_client_reset (client_task, error); +- if (!ret) { +- pk_warning ("failed to reset"); +- return FALSE; ++ /* get the requires packages for each package_id */ ++ length = g_strv_length (package_ids); ++ for (i=0; i<length; i++) { ++ ret = pk_client_reset (client_task, error); ++ if (!ret) { ++ pk_warning ("failed to reset"); ++ break; ++ } ++ ++ pk_debug ("Getting installed requires for %s", package_ids[i]); ++ /* see if any packages require this one */ ++ ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_ids[i], TRUE, error); ++ if (!ret) { ++ pk_warning ("failed to get requires"); ++ break; ++ } ++ ++ /* see how many packages there are */ ++ size = pk_client_package_buffer_get_size (client_task); ++ for (j=0; j<size; j++) { ++ item = pk_client_package_buffer_get_item (client_task, j); ++ pk_package_list_add_item (list, item); ++ } + } + +- pk_debug ("Getting installed requires for %s", package_id); +- ret = pk_client_get_requires (client_task, PK_FILTER_ENUM_INSTALLED, package_id, TRUE, error); ++ /* one of the get-requires failed */ + if (!ret) { +- return FALSE; ++ goto out; + } + +- /* see how many packages there are */ +- length = pk_client_package_buffer_get_size (client_task); +- + /* if there are no required packages, just do the remove */ ++ length = pk_package_list_get_size (list); + if (length == 0) { + pk_debug ("no requires"); +- ret = pk_console_remove_only (client, package_id, FALSE, FALSE, error); +- g_free (package_id); +- return ret; ++ ret = pk_console_remove_only (client, package_ids, FALSE, error); ++ goto out; + } + ++ + /* present this to the user */ + if (awaiting_space) { + g_print ("\n"); + } + g_print ("%s:\n", _("The following packages have to be removed")); + for (i=0; i<length; i++) { +- item = pk_client_package_buffer_get_item (client_task, i); ++ item = pk_package_list_get_item (list, 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); +@@ -694,14 +808,17 @@ pk_console_remove_package (PkClient *client, const gchar *package, GError **erro + /* we chickened out */ + if (remove == FALSE) { + g_print ("%s\n", _("Cancelled!")); +- g_free (package_id); +- return FALSE; ++ ret = FALSE; ++ goto out; + } + + /* remove all the stuff */ +- ret = pk_console_remove_only (client, package_id, TRUE, FALSE, error); +- g_free (package_id); ++ ret = pk_console_remove_only (client, package_ids, TRUE, error); + ++out: ++ g_object_unref (list); ++ g_strfreev (package_ids); ++ g_ptr_array_free (array, TRUE); + return ret; + } + +@@ -840,7 +957,7 @@ pk_console_error_code_cb (PkClient *client, PkErrorCodeEnum error_code, const gc + error_code == PK_ERROR_ENUM_MISSING_GPG_SIGNATURE && trusted) { + pk_debug ("need to try again with trusted FALSE"); + trusted = FALSE; +- ret = pk_client_install_file (client_install_files, trusted, filename, &error); ++ ret = pk_client_install_files (client_install_files, trusted, files_cache, &error); + /* we succeeded, so wait for the requeue */ + if (!ret) { + pk_warning ("failed to install file second time: %s", error->message); +@@ -1153,7 +1270,6 @@ main (int argc, char *argv[]) + const gchar *value = NULL; + const gchar *details = NULL; + const gchar *parameter = NULL; +- PkRoleEnum roles; + PkGroupEnum groups; + gchar *text; + ret = FALSE; +@@ -1324,15 +1440,7 @@ main (int argc, char *argv[]) + 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, trusted, value, &error); +- /* we need this for the untrusted try */ +- filename = g_strdup (value); +- } else { +- ret = pk_console_install_package (client, value, &error); +- } ++ ret = pk_console_install_stuff (client, argv, &error); + + } else if (strcmp (mode, "install-sig") == 0) { + if (value == NULL || details == NULL || parameter == NULL) { +@@ -1346,7 +1454,7 @@ main (int argc, char *argv[]) + g_print (_("You need to specify a package to remove")); + goto out; + } +- ret = pk_console_remove_package (client, value, &error); ++ ret = pk_console_remove_packages (client, argv, &error); + + } else if (strcmp (mode, "accept-eula") == 0) { + if (value == NULL) { +@@ -1465,9 +1573,9 @@ main (int argc, char *argv[]) + 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_strdelimit (text, ";", '\n'); ++ g_print ("%s\n", text); + g_free (text); + maybe_sync = FALSE; + /* these can never fail */ +@@ -1476,7 +1584,8 @@ main (int argc, char *argv[]) + } 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_strdelimit (text, ";", '\n'); ++ g_print ("%s\n", text); + g_free (text); + maybe_sync = FALSE; + /* these can never fail */ +@@ -1485,7 +1594,8 @@ main (int argc, char *argv[]) + } 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_strdelimit (text, ";", '\n'); ++ g_print ("%s\n", text); + g_free (text); + maybe_sync = FALSE; + /* these can never fail */ +@@ -1525,7 +1635,7 @@ out: + g_free (options_help); + g_free (filter); + g_free (summary); +- g_free (filename); ++ g_strfreev (files_cache); + g_object_unref (control); + g_object_unref (client); + g_object_unref (client_task); +diff --git a/configure.ac b/configure.ac +index 9d734e1..f614d2b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -535,7 +535,7 @@ if test x$enable_box = xyes; then + fi + + if test x$enable_opkg = xyes; then +- PKG_CHECK_MODULES(OPKG, libopkg = 0.1.3) ++ PKG_CHECK_MODULES(OPKG, libopkg = 0.1.4) + AC_SUBST(OPKG_CFLAGS) + AC_SUBST(OPKG_LIBS) + fi +diff --git a/contrib/yum-packagekit/refresh-packagekit.py b/contrib/yum-packagekit/refresh-packagekit.py +index 9c0bdf4..b440539 100644 +--- a/contrib/yum-packagekit/refresh-packagekit.py ++++ b/contrib/yum-packagekit/refresh-packagekit.py +@@ -35,7 +35,7 @@ def posttrans_hook(conduit): + '/org/freedesktop/PackageKit') + packagekit_iface = dbus.Interface(packagekit_proxy, 'org.freedesktop.PackageKit') + packagekit_iface.StateHasChanged('posttrans') +- except dbus.DBusException, e: ++ except Exception, e: + conduit.info(2, "Unable to send message to PackageKit") + conduit.info(6, "%s" %(e,)) + +diff --git a/data/tests/Makefile.am b/data/tests/Makefile.am +index d15dd6c..6935e66 100644 +--- a/data/tests/Makefile.am ++++ b/data/tests/Makefile.am +@@ -5,6 +5,7 @@ NULL = + + TEST_FILES = \ + pk-spawn-test.sh \ ++ pk-spawn-proxy.sh \ + pk-spawn-test-sigquit.sh \ + pk-spawn-test-profiling.sh \ + $(NULL) +diff --git a/data/tests/pk-spawn-proxy.sh b/data/tests/pk-spawn-proxy.sh +new file mode 100755 +index 0000000..57774f1 +--- /dev/null ++++ b/data/tests/pk-spawn-proxy.sh +@@ -0,0 +1,20 @@ ++#!/bin/bash ++# Copyright (C) 2008 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. ++ ++if [ -z "${http_proxy}" ]; then ++ echo "no http proxy" ++ exit 1 ++fi ++ ++if [ -z "${ftp_proxy}" ]; then ++ echo "no ftp proxy" ++ exit 1 ++fi ++ ++echo -e "percentage\t100" ++ +diff --git a/docs/html/index.html b/docs/html/index.html +index 7270eb7..d60f825 100644 +--- a/docs/html/index.html ++++ b/docs/html/index.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + <td width="95%" valign="middle"><p class="title">PackageKit Main Page</p></td> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + </tr> + </table> + +@@ -20,10 +20,10 @@ + <table align="center" cellpadding="5px" border="0"> + + <tr> +- <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt="[img]"/></a></td> +- <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt="[img]"/></a></td> +- <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt="[img]"/></a></td> +- <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt="[img]"/></a></td> ++ <td align="center"><a href="pk-intro.html"><img src="img/large-accessories-text-editor.png" width="128" alt=""/></a></td> ++ <td align="center"><a href="pk-using.html"><img src="img/large-preferences-system.png" width="128" alt=""/></a></td> ++ <td align="center"><a href="pk-download.html"><img src="img/large-dialog-information.png" width="128" alt=""/></a></td> ++ <td align="center"><a href="pk-screenshots.html"><img src="img/large-emblem-photos.png" width="128" alt=""/></a></td> + </tr> + <tr> + <td><p class="indextitle"><a href="pk-intro.html" class="indextitle">What is<br/>PackageKit?</a></p></td> +@@ -32,10 +32,10 @@ + <td><p class="indextitle"><a href="pk-screenshots.html" class="indextitle">Screenshots</a></p></td> + </tr> + <tr> +- <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt="[img]"/></a></td> +- <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt="[img]"/></a></td> +- <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt="[img]"/></a></td> +- <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt="[img]"/></a></td> ++ <td align="center"><a href="pk-authors.html"><img src="img/large-authors.png" width="128" alt=""/></a></td> ++ <td align="center"><a href="pk-bugs.html"><img src="img/large-applications-development.png" width="128" alt=""/></a></td> ++ <td align="center"><a href="pk-help.html"><img src="img/large-system-users.png" width="128" alt=""/></a></td> ++ <td align="center"><a href="pk-faq.html"><img src="img/large-help-browser.png" width="128" alt=""/></a></td> + </tr> + <tr> + <td><p class="indextitle"><a href="pk-authors.html" class="indextitle">Who develops<br/>PackageKit?</a></p></td> +diff --git a/docs/html/pk-authors.html b/docs/html/pk-authors.html +index 08289ad..607a7a4 100644 +--- a/docs/html/pk-authors.html ++++ b/docs/html/pk-authors.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + <td width="95%" valign="middle"><p class="title">Who develops PackageKit?</p></td> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + </tr> + </table> + +@@ -22,7 +22,7 @@ + <table cellpadding="10"> + <tr> + <td> +- <img src="img/author-hughsie.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-hughsie.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Richard Hughes</h2> +@@ -48,7 +48,7 @@ + + <tr> + <td> +- <img src="img/author-kenvandine.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-kenvandine.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Ken VanDine</h2> +@@ -66,7 +66,7 @@ + + <tr> + <td> +- <img src="img/author-btimothy.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-btimothy.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Boyd Timothy</h2> +@@ -84,7 +84,7 @@ + + <tr> + <td> +- <img src="img/author-rnorwood.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-rnorwood.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Robin Norwood</h2> +@@ -101,7 +101,7 @@ + + <tr> + <td> +- <img src="img/author-tomparker.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-tomparker.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Tom Parker</h2> +@@ -118,7 +118,7 @@ + + <tr> + <td> +- <img src="img/author-timlau.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-timlau.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Tim Lauridsen</h2> +@@ -139,7 +139,7 @@ + + <tr> + <td> +- <img src="img/author-lmacken.png" alt="[img]"/> ++ <img src="img/author-lmacken.png" alt=""/> + </td> + <td> + <h2>Luke Macken</h2> +@@ -154,7 +154,7 @@ + + <tr> + <td> +- <img src="img/author-grzegorzdabrowski.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-grzegorzdabrowski.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Grzegorz Dąbrowski</h2> +@@ -173,7 +173,7 @@ + + <tr> + <td> +- <img src="img/author-caglar.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-caglar.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>S.Çağlar Onur</h2> +@@ -195,7 +195,7 @@ + + <tr> + <td> +- <img src="img/author-elliot.png" alt="[img]"/> ++ <img src="img/author-elliot.png" alt=""/> + </td> + <td> + <h2>Elliot Peele</h2> +@@ -210,7 +210,7 @@ + + <tr> + <td> +- <img src="img/author-jbowes.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-jbowes.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>James Bowes</h2> +@@ -227,7 +227,7 @@ + + <tr> + <td> +- <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Thomas Wood</h2> +@@ -247,7 +247,7 @@ + + <tr> + <td> +- <img src="img/author-unknown.png" alt="[img]"/><!-- image should be 120px wide --> ++ <img src="img/author-unknown.png" alt=""/><!-- image should be 120px wide --> + </td> + <td> + <h2>Scott Reeves</h2> +diff --git a/docs/html/pk-bugs.html b/docs/html/pk-bugs.html +index 89f7c48..2ee12ea 100644 +--- a/docs/html/pk-bugs.html ++++ b/docs/html/pk-bugs.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + <td width="95%" valign="middle"><p class="title">Reporting Bugs</p></td> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + </tr> + </table> + +diff --git a/docs/html/pk-download.html b/docs/html/pk-download.html +index 6f796b8..0cdc85c 100644 +--- a/docs/html/pk-download.html ++++ b/docs/html/pk-download.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + <td width="95%" valign="middle"><p class="title">Where can I download it?</p></td> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + </tr> + </table> + +diff --git a/docs/html/pk-faq.html b/docs/html/pk-faq.html +index a25e2b7..efa8344 100644 +--- a/docs/html/pk-faq.html ++++ b/docs/html/pk-faq.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td> ++ <td><center><img src="img/packagekit.png" alt=""/></center></td> + <td width="95%" valign="middle"><p class="title">Frequently Asked Questions</p></td> +- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td> ++ <td><center><img src="img/packagekit.png" alt=""/></center></td> + </tr> + </table> + +@@ -22,6 +22,7 @@ + <h2>Table Of Contents</h2> + <ul> + <li><a href="#how-complete">How complete are the backends?</a></li> ++<li><a href="#run-as-root">When run as root, gpk-application and pkcon do not work!</a></li> + <li><a href="#session-system">Why is there a session service and and a system service?</a></li> + <li><a href="#session-methods">How do I use PackageKit in my application?</a></li> + <li><a href="#rawhide-updates">Why don't I get update details with Fedora Rawhide?</a></li> +@@ -565,6 +566,19 @@ + </table> + + <hr> ++<h3><a name="run-as-root">When run as root, <code>gpk-application</code> and <code>pkcon</code> do not work!</a></h3> ++<p> ++GTK+ tools should not be run as the root user, <b>PERIOD</b>. ++Any GTK+ program run as the root user is a massive security hole -- GTK+ just isn't designed with ++this in mind. ++There are <b>numerous</b> attack vectors when running as root, and programs shouldn't do such ++insane and insecure things. ++</p> ++<p> ++Please see <a href="http://www.gtk.org/setuid.html">the GTK+ explanation</a> for more rationale. ++</p> ++ ++<hr> + <h3><a name="session-system">Why is there a session service <b>and</b> and a system service?</a></h3> + <p> + PackageKit runs a process <code>packagekitd</code> that is a daemon that runs per-system. +diff --git a/docs/html/pk-help.html b/docs/html/pk-help.html +index 5b44d50..5bc7827 100644 +--- a/docs/html/pk-help.html ++++ b/docs/html/pk-help.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + <td width="95%" valign="middle"><p class="title">How can I help?</p></td> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + </tr> + </table> + +@@ -72,9 +72,9 @@ as for instructions! + <b>0.2.2</b> - To be released June 2008 + </p> + <ul> +-<li>Multiple package install and remove from pkcon <i>(0%)</i></li> ++<li>Network proxy server support <i>(70%)</i></li> ++<li>Multiple package install and remove from pkcon <i>(80%)</i></li> + <li>NetworkManager integration so we can detect GPRS (and modem) connections. <i>(10%)</i></li> +-<li>Filter for source packages. <i>(0%)</i></li> + </ul> + <p> + <b>0.2.3</b> - To be released July 2008 +@@ -84,6 +84,12 @@ as for instructions! + <li>Multiple package installs from gpk-application <i>(0%)</i></li> + <li>Ignoring packages from the update viewer per-session <i>(10%)</i></li> + </ul> ++<p> ++<b>0.3.0</b> - To be released December 2008 ++</p> ++<ul> ++<li>More composite types <code>s</code> to <code>as</code> <i>(0%)</i></li> ++</ul> + + <p>Back to the <a href="index.html">main page</a></p> + +diff --git a/docs/html/pk-intro.html b/docs/html/pk-intro.html +index c42be21..64f72fc 100644 +--- a/docs/html/pk-intro.html ++++ b/docs/html/pk-intro.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + <td width="95%" valign="middle"><p class="title">What is PackageKit?</p></td> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + </tr> + </table> + +diff --git a/docs/html/pk-screenshots.html b/docs/html/pk-screenshots.html +index 78bd01f..5c7d4fa 100644 +--- a/docs/html/pk-screenshots.html ++++ b/docs/html/pk-screenshots.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td> ++ <td><center><img src="img/packagekit.png" alt=""/></center></td> + <td width="95%" valign="middle"><p class="title">Screenshots</p></td> +- <td><center><img src="img/packagekit.png" alt="[img]"/></center></td> ++ <td><center><img src="img/packagekit.png" alt=""/></center></td> + </tr> + </table> + +@@ -26,77 +26,77 @@ + + <h1><a name="gnome">GNOME Screenshots</a></h1> + +-<center><img src="img/gpk-application-search.png" alt="[img]"/></center> ++<center><img src="img/gpk-application-search.png" alt=""/></center> + <p class="caption">Add/Remove Software search</p> + +-<center><img src="img/gpk-application-groups.png" alt="[img]"/></center> ++<center><img src="img/gpk-application-groups.png" alt=""/></center> + <p class="caption">Add/Remove Software groups</p> + +-<center><img src="img/gpk-log.png" alt="[img]"/></center> ++<center><img src="img/gpk-log.png" alt=""/></center> + <p class="caption">Transaction viewer</p> + +-<center><img src="img/gpk-updates-overview.png" alt="[img]"/></center> ++<center><img src="img/gpk-updates-overview.png" alt=""/></center> + <p class="caption">Update viewer overview</p> + +-<center><img src="img/gpk-updates.png" alt="[img]"/></center> ++<center><img src="img/gpk-updates.png" alt=""/></center> + <p class="caption">Update viewer</p> + +-<center><img src="img/gpk-prefs.png" alt="[img]"/></center> ++<center><img src="img/gpk-prefs.png" alt=""/></center> + <p class="caption">Auto update preferences</p> + +-<center><img src="img/gpk-progress.png" alt="[img]"/></center> ++<center><img src="img/gpk-progress.png" alt=""/></center> + <p class="caption">Progress dialog</p> + +-<center><img src="img/gpk-added-deps.png" alt="[img]"/></center> ++<center><img src="img/gpk-added-deps.png" alt=""/></center> + <p class="caption">Added check warning</p> + +-<center><img src="img/gpk-eula.png" alt="[img]"/></center> ++<center><img src="img/gpk-eula.png" alt=""/></center> + <p class="caption">EULA dialog</p> + +-<center><img src="img/gpk-remove-confirm.png" alt="[img]"/></center> ++<center><img src="img/gpk-remove-confirm.png" alt=""/></center> + <p class="caption">Remove check warning</p> + +-<center><img src="img/gpk-repo-auth.png" alt="[img]"/></center> ++<center><img src="img/gpk-repo-auth.png" alt=""/></center> + <p class="caption">Repository authentication</p> + +-<center><img src="img/gpk-repo.png" alt="[img]"/></center> ++<center><img src="img/gpk-repo.png" alt=""/></center> + <p class="caption">Repository viewer</p> + +-<center><img src="img/gpk-backend-status.png" alt="[img]"/></center> ++<center><img src="img/gpk-backend-status.png" alt=""/></center> + <p class="caption">PackageKit backend status</p> + +-<center><img src="img/gpk-updates-warning.png" alt="[img]"/></center> ++<center><img src="img/gpk-updates-warning.png" alt=""/></center> + <p class="caption">Libnotify updates warning</p> + +-<center><img src="img/gpk-waiting.png" alt="[img]"/></center> ++<center><img src="img/gpk-waiting.png" alt=""/></center> + <p class="caption">Tasks waiting</p> + +-<center><img src="img/gpk-battery.png" alt="[img]"/></center> ++<center><img src="img/gpk-battery.png" alt=""/></center> + <p class="caption">Intergration with gnome-power-manager</p> + +-<center><img src="img/gpk-inhibit.png" alt="[img]"/></center> ++<center><img src="img/gpk-inhibit.png" alt=""/></center> + <p class="caption">Inhibit with gnome-power-manager</p> + +-<center><img src="img/gpk-require-restart.png" alt="[img]"/></center> ++<center><img src="img/gpk-require-restart.png" alt=""/></center> + <p class="caption">We sometimes need to do a restart</p> + +-<center><img src="img/gpk-auto-update.png" alt="[img]"/></center> ++<center><img src="img/gpk-auto-update.png" alt=""/></center> + <p class="caption">Auto update install dialog</p> + + <h1><a name="kde">KDE Screenshots</a></h1> + +-<center><img src="img/kpk-search.png" alt="[img]"/></center> ++<center><img src="img/kpk-search.png" alt=""/></center> + <p class="caption">KPackageKit Searching</p> + +-<center><img src="img/kpk-information.png" alt="[img]"/></center> ++<center><img src="img/kpk-information.png" alt=""/></center> + <p class="caption">KPackageKit Package Information</p> + +-<center><img src="img/pk-opensuse-updater.png" alt="[img]"/></center> ++<center><img src="img/pk-opensuse-updater.png" alt=""/></center> + <p class="caption">OpenSuse Updater</p> + + <h1><a name="moko">OpenMoko Screenshots</a></h1> + +-<center><img src="img/assassin.png" alt="[img]"/></center> ++<center><img src="img/assassin.png" alt=""/></center> + <p class="caption">Assassin</p> + + <p>Back to the <a href="index.html">main page</a></p> +diff --git a/docs/html/pk-using.html b/docs/html/pk-using.html +index cc455c7..b2b028e 100644 +--- a/docs/html/pk-using.html ++++ b/docs/html/pk-using.html +@@ -9,9 +9,9 @@ + + <table align="center" class="title"> + <tr> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + <td width="95%" valign="middle"><p class="title">How do I use PackageKit?</p></td> +- <td><img src="img/packagekit.png" alt="[img]"/></td> ++ <td><img src="img/packagekit.png" alt=""/></td> + </tr> + </table> + +diff --git a/docs/spec/pk-concepts.xml b/docs/spec/pk-concepts.xml +index 312c5a4..0b75b10 100644 +--- a/docs/spec/pk-concepts.xml ++++ b/docs/spec/pk-concepts.xml +@@ -127,6 +127,13 @@ + This allows the used to choose non-native packages if a multi-lib policy is allowed. + </entry> + </row> ++ <row> ++ <entry><literal>source</literal> or <literal>~source</literal></entry> ++ <entry> ++ The source filter will only return source packages. ++ These are typically useful when rebuilding other packages. ++ </entry> ++ </row> + </tbody> + </tgroup> + </informaltable> +diff --git a/etc/PackageKit.conf.in b/etc/PackageKit.conf.in +index a6af99b..8f9bd57 100644 +--- a/etc/PackageKit.conf.in ++++ b/etc/PackageKit.conf.in +@@ -31,3 +31,13 @@ ShutdownTimeout=300 + # default=@defaultbackend@ + DefaultBackend=@defaultbackend@ + ++# Proxy settings, uncomment as required ++# ++# NOTE: PackageKit does not use these settings, they are passed to backends. ++# Backends may ignore these values, or they may be updated from the session. ++# ++# They are in the format username:password@server:port ++# ++# ProxyHTTP=username:password@server.lan:8080 ++# ProxyFTP=username:password@server.lan:21 ++ +diff --git a/libpackagekit/Makefile.am b/libpackagekit/Makefile.am +index 6b8c6b8..aeafe44 100644 +--- a/libpackagekit/Makefile.am ++++ b/libpackagekit/Makefile.am +@@ -37,6 +37,7 @@ libpackagekit_include_HEADERS = \ + pk-connection.h \ + pk-package-id.h \ + pk-package-ids.h \ ++ pk-package-item.h \ + pk-package-list.h \ + pk-enum.h \ + pk-common.h \ +@@ -59,6 +60,8 @@ libpackagekit_la_SOURCES = \ + pk-package-id.h \ + pk-package-ids.c \ + pk-package-ids.h \ ++ pk-package-item.c \ ++ pk-package-item.h \ + pk-package-list.c \ + pk-package-list.h \ + pk-enum.h \ +diff --git a/libpackagekit/pk-enum.c b/libpackagekit/pk-enum.c +index b5b6ac3..5743dcb 100644 +--- a/libpackagekit/pk-enum.c ++++ b/libpackagekit/pk-enum.c +@@ -193,6 +193,8 @@ static PkEnumMatch enum_filter[] = { + {PK_FILTER_ENUM_NOT_NEWEST, "~newest"}, + {PK_FILTER_ENUM_ARCH, "arch"}, + {PK_FILTER_ENUM_NOT_ARCH, "~arch"}, ++ {PK_FILTER_ENUM_SOURCE, "source"}, ++ {PK_FILTER_ENUM_NOT_SOURCE, "~source"}, + {0, NULL} + }; + +diff --git a/libpackagekit/pk-enum.h b/libpackagekit/pk-enum.h +index 33e8a91..e616b64 100644 +--- a/libpackagekit/pk-enum.h ++++ b/libpackagekit/pk-enum.h +@@ -182,7 +182,9 @@ typedef enum { + PK_FILTER_ENUM_NOT_NEWEST = 1 << 15, + PK_FILTER_ENUM_ARCH = 1 << 16, + PK_FILTER_ENUM_NOT_ARCH = 1 << 17, +- PK_FILTER_ENUM_UNKNOWN = 1 << 18 ++ PK_FILTER_ENUM_SOURCE = 1 << 18, ++ PK_FILTER_ENUM_NOT_SOURCE = 1 << 19, ++ PK_FILTER_ENUM_UNKNOWN = 1 << 20 + } PkFilterEnum; + + /** +diff --git a/libpackagekit/pk-package-item.c b/libpackagekit/pk-package-item.c +new file mode 100644 +index 0000000..87905dc +--- /dev/null ++++ b/libpackagekit/pk-package-item.c +@@ -0,0 +1,190 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2007-2008 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. ++ */ ++ ++/** ++ * SECTION:pk-package-item ++ * @short_description: A cached Package structure ++ * ++ * These provide a way to query and store a single package. ++ */ ++ ++#include "config.h" ++ ++#include <stdlib.h> ++#include <stdio.h> ++#include <time.h> ++#include <errno.h> ++ ++#include <string.h> ++#include <sys/time.h> ++#include <sys/types.h> ++#ifdef HAVE_UNISTD_H ++#include <unistd.h> ++#endif /* HAVE_UNISTD_H */ ++ ++#include <glib/gi18n.h> ++ ++#include "pk-debug.h" ++#include "pk-common.h" ++#include "pk-package-item.h" ++ ++/** ++ * pk_package_item_new: ++ **/ ++PkPackageItem * ++pk_package_item_new (PkInfoEnum info, const gchar *package_id, const gchar *summary) ++{ ++ PkPackageItem *item; ++ ++ g_return_val_if_fail (package_id != NULL, FALSE); ++ ++ pk_debug ("adding to cache item package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary); ++ item = g_new0 (PkPackageItem, 1); ++ item->info = info; ++ item->package_id = g_strdup (package_id); ++ item->summary = g_strdup (summary); ++ return item; ++} ++ ++/** ++ * pk_package_item_free: ++ **/ ++gboolean ++pk_package_item_free (PkPackageItem *item) ++{ ++ if (item == NULL) { ++ return FALSE; ++ } ++ g_free (item->package_id); ++ g_free (item->summary); ++ g_free (item); ++ return TRUE; ++} ++ ++/** ++ * pk_package_item_equal: ++ * ++ * Only compares the package_id's and the info enum ++ **/ ++gboolean ++pk_package_item_equal (PkPackageItem *item1, PkPackageItem *item2) ++{ ++ if (item1 == NULL || item2 == NULL) { ++ return FALSE; ++ } ++ return (item1->info == item2->info && ++ pk_strequal (item1->package_id, item2->package_id)); ++} ++ ++/** ++ * pk_package_item_copy: ++ * ++ * Copy a PkPackageItem ++ **/ ++PkPackageItem * ++pk_package_item_copy (PkPackageItem *item) ++{ ++ g_return_val_if_fail (item != NULL, NULL); ++ return pk_package_item_new (item->info, item->package_id, item->summary); ++} ++ ++/*************************************************************************** ++ *** MAKE CHECK TESTS *** ++ ***************************************************************************/ ++#ifdef PK_BUILD_TESTS ++#include <libselftest.h> ++ ++void ++libst_package_item (LibSelfTest *test) ++{ ++ PkPackageItem *item1; ++ PkPackageItem *item2; ++ PkPackageItem *item3; ++ gboolean ret; ++ ++ if (libst_start (test, "PkPackageItem", CLASS_AUTO) == FALSE) { ++ return; ++ } ++ ++ /************************************************************/ ++ libst_title (test, "add entry"); ++ item1 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME!"); ++ if (item1 != NULL) { ++ libst_success (test, NULL); ++ } else { ++ libst_failed (test, NULL); ++ } ++ ++ /************************************************************/ ++ libst_title (test, "add entry"); ++ item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome;1.23;i386;data", "GNOME foo!"); ++ if (item2 != NULL) { ++ libst_success (test, NULL); ++ } else { ++ libst_failed (test, NULL); ++ } ++ ++ /************************************************************/ ++ libst_title (test, "copy entry"); ++ item3 = pk_package_item_copy (item2); ++ if (item3 != NULL) { ++ libst_success (test, NULL); ++ } else { ++ libst_failed (test, NULL); ++ } ++ ++ /************************************************************/ ++ libst_title (test, "check equal"); ++ ret = pk_package_item_equal (item1, item3); ++ if (ret) { ++ libst_success (test, NULL); ++ } else { ++ libst_failed (test, NULL); ++ } ++ ++ pk_package_item_free (item2); ++ pk_package_item_free (item3); ++ ++ /************************************************************/ ++ libst_title (test, "add entry"); ++ item2 = pk_package_item_new (PK_INFO_ENUM_INSTALLED, "gnome-do;1.23;i386;data", "GNOME doo!"); ++ if (item2 != NULL) { ++ libst_success (test, NULL); ++ } else { ++ libst_failed (test, NULL); ++ } ++ ++ /************************************************************/ ++ libst_title (test, "check !equal"); ++ ret = pk_package_item_equal (item1, item2); ++ if (!ret) { ++ libst_success (test, NULL); ++ } else { ++ libst_failed (test, NULL); ++ } ++ ++ pk_package_item_free (item1); ++ pk_package_item_free (item2); ++ ++ libst_end (test); ++} ++#endif ++ +diff --git a/libpackagekit/pk-package-item.h b/libpackagekit/pk-package-item.h +new file mode 100644 +index 0000000..c41a6ea +--- /dev/null ++++ b/libpackagekit/pk-package-item.h +@@ -0,0 +1,48 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2008 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. ++ */ ++ ++#ifndef __PK_PACKAGE_ITEM_H ++#define __PK_PACKAGE_ITEM_H ++ ++#include <glib-object.h> ++#include <pk-enum.h> ++ ++/** ++ * PkPackageItem: ++ * ++ * A cached store for the complete Package object ++ */ ++typedef struct { ++ PkInfoEnum info; ++ gchar *package_id; ++ gchar *summary; ++} PkPackageItem; ++ ++PkPackageItem *pk_package_item_new (PkInfoEnum info, ++ const gchar *package_id, ++ const gchar *summary); ++gboolean pk_package_item_free (PkPackageItem *item); ++PkPackageItem *pk_package_item_copy (PkPackageItem *item); ++gboolean pk_package_item_equal (PkPackageItem *item1, ++ PkPackageItem *item2); ++ ++#endif /* __PK_PACKAGE_ITEM_H */ ++ +diff --git a/libpackagekit/pk-package-list.c b/libpackagekit/pk-package-list.c +index b0a1a71..5d95e1b 100644 +--- a/libpackagekit/pk-package-list.c ++++ b/libpackagekit/pk-package-list.c +@@ -45,6 +45,7 @@ + #include "pk-debug.h" + #include "pk-common.h" + #include "pk-package-id.h" ++#include "pk-package-item.h" + #include "pk-package-list.h" + + static void pk_package_list_class_init (PkPackageListClass *klass); +@@ -77,16 +78,42 @@ pk_package_list_add (PkPackageList *plist, PkInfoEnum info, const gchar *package + g_return_val_if_fail (package_id != NULL, FALSE); + + pk_debug ("adding to cache array package %s, %s, %s", pk_info_enum_to_text (info), package_id, summary); +- item = g_new0 (PkPackageItem, 1); +- item->info = info; +- item->package_id = g_strdup (package_id); +- item->summary = g_strdup (summary); ++ item = pk_package_item_new (info, package_id, summary); + g_ptr_array_add (plist->priv->array, item); + + return TRUE; + } + + /** ++ * pk_package_list_add_item: ++ * ++ * Makes a deep copy, and adds to the array ++ **/ ++gboolean ++pk_package_list_add_item (PkPackageList *plist, PkPackageItem *item) ++{ ++ gboolean ret; ++ PkPackageItem *item_new; ++ ++ g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE); ++ g_return_val_if_fail (item != NULL, FALSE); ++ ++ ret = pk_package_list_contains_item (plist, item); ++ if (ret) { ++ pk_debug ("already added item"); ++ return FALSE; ++ } ++ ++ pk_debug ("adding to cache array package %s, %s, %s", ++ pk_info_enum_to_text (item->info), item->package_id, item->summary); ++ ++ item_new = pk_package_item_copy (item); ++ g_ptr_array_add (plist->priv->array, item_new); ++ ++ return TRUE; ++} ++ ++/** + * pk_package_list_get_string: + **/ + gchar * +@@ -152,9 +179,7 @@ pk_package_list_clear (PkPackageList *plist) + + while (plist->priv->array->len > 0) { + item = g_ptr_array_index (plist->priv->array, 0); +- g_free (item->package_id); +- g_free (item->summary); +- g_free (item); ++ pk_package_item_free (item); + g_ptr_array_remove_index_fast (plist->priv->array, 0); + } + return TRUE; +@@ -186,6 +211,31 @@ pk_package_list_contains (PkPackageList *plist, const gchar *package_id) + } + + /** ++ * pk_package_list_contains_item: ++ **/ ++gboolean ++pk_package_list_contains_item (PkPackageList *plist, PkPackageItem *item) ++{ ++ PkPackageItem *item_temp; ++ guint i; ++ guint length; ++ gboolean ret = FALSE; ++ ++ g_return_val_if_fail (PK_IS_PACKAGE_LIST (plist), FALSE); ++ g_return_val_if_fail (item != NULL, FALSE); ++ ++ length = plist->priv->array->len; ++ for (i=0; i<length; i++) { ++ item_temp = g_ptr_array_index (plist->priv->array, i); ++ ret = pk_package_item_equal (item_temp, item); ++ if (ret) { ++ break; ++ } ++ } ++ return ret; ++} ++ ++/** + * pk_package_list_class_init: + * @klass: The PkPackageListClass + **/ +diff --git a/libpackagekit/pk-package-list.h b/libpackagekit/pk-package-list.h +index 9178f77..9734af4 100644 +--- a/libpackagekit/pk-package-list.h ++++ b/libpackagekit/pk-package-list.h +@@ -25,6 +25,8 @@ + #include <glib-object.h> + #include <pk-enum.h> + ++#include "pk-package-item.h" ++ + G_BEGIN_DECLS + + #define PK_TYPE_PACKAGE_LIST (pk_package_list_get_type ()) +@@ -49,26 +51,18 @@ struct _PkPackageListClass + GObjectClass parent_class; + }; + +-/** +- * PkPackageItem: +- * +- * A cached store for the complete Package object +- */ +-typedef struct +-{ +- PkInfoEnum info; +- gchar *package_id; +- gchar *summary; +-} PkPackageItem; +- + GType pk_package_list_get_type (void) G_GNUC_CONST; + PkPackageList *pk_package_list_new (void); + gboolean pk_package_list_add (PkPackageList *plist, + PkInfoEnum info, + const gchar *package_id, + const gchar *summary); ++gboolean pk_package_list_add_item (PkPackageList *plist, ++ PkPackageItem *item); + gboolean pk_package_list_contains (PkPackageList *plist, + const gchar *package_id); ++gboolean pk_package_list_contains_item (PkPackageList *plist, ++ PkPackageItem *item); + gchar *pk_package_list_get_string (PkPackageList *plist) + G_GNUC_WARN_UNUSED_RESULT; + guint pk_package_list_get_size (PkPackageList *plist); +diff --git a/libpackagekit/pk-self-test.c b/libpackagekit/pk-self-test.c +index 62e225b..bf151fb 100644 +--- a/libpackagekit/pk-self-test.c ++++ b/libpackagekit/pk-self-test.c +@@ -29,6 +29,7 @@ + /* prototypes */ + void libst_package_id (LibSelfTest *test); + void libst_package_ids (LibSelfTest *test); ++void libst_package_item (LibSelfTest *test); + void libst_package_list (LibSelfTest *test); + void libst_enum (LibSelfTest *test); + void libst_common (LibSelfTest *test); +@@ -51,6 +52,7 @@ main (int argc, char **argv) + libst_common (&test); + libst_package_id (&test); + libst_package_ids (&test); ++ libst_package_item (&test); + libst_package_list (&test); + libst_enum (&test); + libst_extra (&test); +diff --git a/python/packagekit/daemonBackend.py b/python/packagekit/daemonBackend.py +index 3711f01..5253b39 100644 +--- a/python/packagekit/daemonBackend.py ++++ b/python/packagekit/daemonBackend.py +@@ -789,6 +789,21 @@ class PackageKitBaseBackend(dbus.service.Object): + self.Finished(EXIT_FAILED) + + @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE, ++ in_signature='ss', out_signature='') ++ def SetProxy(self, proxy_http, proxy_ftp): ++ ''' ++ Set the proxy ++ ''' ++ pklog.info("SetProxy(%s, %s)" % (proxy_http, proxy_ftp)) ++ self.doSetProxy(proxy_http, proxy_ftp) ++ ++ def doSetProxy(self, proxy_http, proxy_ftp): ++ ''' ++ Should be replaced in the corresponding backend sub class ++ ''' ++ # do not use Finished() in this method ++ ++ @dbus.service.method(PACKAGEKIT_DBUS_INTERFACE, + in_signature='s', out_signature='') + def InstallPublicKey(self, keyurl): + ''' +diff --git a/src/pk-backend-dbus.c b/src/pk-backend-dbus.c +index b06e584..4c6837a 100644 +--- a/src/pk-backend-dbus.c ++++ b/src/pk-backend-dbus.c +@@ -123,16 +123,6 @@ pk_backend_dbus_sub_percentage_changed_cb (DBusGProxy *proxy, guint sub_percenta + } + + /** +- * pk_backend_dbus_no_percentage_updates_cb: +- **/ +-static void +-pk_backend_dbus_no_percentage_updates_cb (DBusGProxy *proxy, PkBackendDbus *backend_dbus) +-{ +- pk_debug ("got signal"); +- pk_backend_no_percentage_updates (backend_dbus->priv->backend); +-} +- +-/** + * pk_backend_dbus_package_cb: + **/ + static void +@@ -325,8 +315,6 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus) + G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus); + dbus_g_proxy_disconnect_signal (proxy, "SubPercentageChanged", + G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus); +- dbus_g_proxy_disconnect_signal (proxy, "NoPercentageChanged", +- G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus); + dbus_g_proxy_disconnect_signal (proxy, "Package", + G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus); + dbus_g_proxy_disconnect_signal (proxy, "Details", +@@ -353,6 +341,31 @@ pk_backend_dbus_remove_callbacks (PkBackendDbus *backend_dbus) + } + + /** ++ * pk_backend_dbus_set_proxy: ++ **/ ++static gboolean ++pk_backend_dbus_set_proxy (PkBackendDbus *backend_dbus, const gchar *proxy_http, const gchar *proxy_ftp) ++{ ++ gboolean ret; ++ GError *error = NULL; ++ ++ g_return_val_if_fail (PK_IS_BACKEND_DBUS (backend_dbus), FALSE); ++ g_return_val_if_fail (backend_dbus->priv->proxy != NULL, FALSE); ++ ++ /* new sync method call */ ++ pk_backend_dbus_time_reset (backend_dbus); ++ ret = dbus_g_proxy_call (backend_dbus->priv->proxy, "SetProxy", &error, ++ G_TYPE_STRING, proxy_http, ++ G_TYPE_STRING, proxy_ftp, ++ G_TYPE_INVALID, G_TYPE_INVALID); ++ if (error != NULL) { ++ pk_warning ("%s", error->message); ++ g_error_free (error); ++ } ++ return ret; ++} ++ ++/** + * pk_backend_dbus_set_name: + **/ + gboolean +@@ -385,7 +398,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service) + G_TYPE_UINT, G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, "SubPercentageChanged", + G_TYPE_UINT, G_TYPE_INVALID); +- dbus_g_proxy_add_signal (proxy, "NoPercentageChanged", G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, "Package", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_add_signal (proxy, "Details", +@@ -424,8 +436,6 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service) + G_CALLBACK (pk_backend_dbus_percentage_changed_cb), backend_dbus, NULL); + dbus_g_proxy_connect_signal (proxy, "SubPercentageChanged", + G_CALLBACK (pk_backend_dbus_sub_percentage_changed_cb), backend_dbus, NULL); +- dbus_g_proxy_connect_signal (proxy, "NoPercentageChanged", +- G_CALLBACK (pk_backend_dbus_no_percentage_updates_cb), backend_dbus, NULL); + dbus_g_proxy_connect_signal (proxy, "Package", + G_CALLBACK (pk_backend_dbus_package_cb), backend_dbus, NULL); + dbus_g_proxy_connect_signal (proxy, "Details", +@@ -465,6 +475,18 @@ pk_backend_dbus_set_name (PkBackendDbus *backend_dbus, const gchar *service) + pk_backend_finished (backend_dbus->priv->backend); + g_error_free (error); + } ++ ++ /* set the proxy */ ++ if (ret) { ++ gchar *proxy_http; ++ gchar *proxy_ftp; ++ proxy_http = pk_backend_get_proxy_http (backend_dbus->priv->backend); ++ proxy_ftp = pk_backend_get_proxy_http (backend_dbus->priv->backend); ++ pk_backend_dbus_set_proxy (backend_dbus, proxy_http, proxy_ftp); ++ g_free (proxy_http); ++ g_free (proxy_ftp); ++ } ++ + if (ret) { + pk_backend_dbus_time_check (backend_dbus); + } +diff --git a/src/pk-backend-internal.h b/src/pk-backend-internal.h +index 2213fed..2bffaff 100644 +--- a/src/pk-backend-internal.h ++++ b/src/pk-backend-internal.h +@@ -59,6 +59,9 @@ gboolean pk_backend_reset (PkBackend *backend); + gboolean pk_backend_set_name (PkBackend *backend, + const gchar *name) + G_GNUC_WARN_UNUSED_RESULT; ++gboolean pk_backend_set_proxy (PkBackend *backend, ++ const gchar *proxy_http, ++ const gchar *proxy_ftp); + gchar *pk_backend_get_name (PkBackend *backend) + G_GNUC_WARN_UNUSED_RESULT; + gboolean pk_backend_get_backend_detail (PkBackend *backend, +diff --git a/src/pk-backend-spawn.c b/src/pk-backend-spawn.c +index f9e8b68..f9c9f12 100644 +--- a/src/pk-backend-spawn.c ++++ b/src/pk-backend-spawn.c +@@ -313,7 +313,7 @@ pk_backend_spawn_parse_stdout (PkBackendSpawn *backend_spawn, const gchar *line) + ret = FALSE; + goto out; + } +- pk_backend_no_percentage_updates (backend_spawn->priv->backend); ++ pk_backend_set_percentage (backend_spawn->priv->backend, PK_BACKEND_PERCENTAGE_INVALID); + } else if (pk_strequal (command, "repo-signature-required")) { + + if (size != 9+99) { +@@ -440,6 +440,44 @@ pk_backend_spawn_helper_new (PkBackendSpawn *backend_spawn) + } + + /** ++ * pk_backend_spawn_get_envp: ++ * ++ * Return all the environment variables the script will need ++ **/ ++static gchar ** ++pk_backend_spawn_get_envp (PkBackendSpawn *backend_spawn) ++{ ++ gchar **envp; ++ gchar *value; ++ gchar *line; ++ GPtrArray *array; ++ ++ array = g_ptr_array_new (); ++ ++ /* http_proxy */ ++ value = pk_backend_get_proxy_http (backend_spawn->priv->backend); ++ if (!pk_strzero (value)) { ++ line = g_strdup_printf ("%s=%s", "http_proxy", value); ++ pk_debug ("setting evp '%s'", line); ++ g_ptr_array_add (array, line); ++ } ++ g_free (value); ++ ++ /* ftp_proxy */ ++ value = pk_backend_get_proxy_ftp (backend_spawn->priv->backend); ++ if (!pk_strzero (value)) { ++ line = g_strdup_printf ("%s=%s", "ftp_proxy", value); ++ pk_debug ("setting evp '%s'", line); ++ g_ptr_array_add (array, line); ++ } ++ g_free (value); ++ ++ envp = pk_ptr_array_to_argv (array); ++ g_ptr_array_free (array, TRUE); ++ return envp; ++} ++ ++/** + * pk_backend_spawn_helper_va_list: + **/ + static gboolean +@@ -448,6 +486,7 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe + gboolean ret; + gchar *filename; + gchar **argv; ++ gchar **envp; + + g_return_val_if_fail (PK_IS_BACKEND_SPAWN (backend_spawn), FALSE); + +@@ -476,7 +515,8 @@ pk_backend_spawn_helper_va_list (PkBackendSpawn *backend_spawn, const gchar *exe + argv[0] = g_strdup (filename); + + pk_backend_spawn_helper_new (backend_spawn); +- ret = pk_spawn_argv (backend_spawn->priv->spawn, argv); ++ envp = pk_backend_spawn_get_envp (backend_spawn); ++ ret = pk_spawn_argv (backend_spawn->priv->spawn, argv, envp); + if (!ret) { + pk_backend_spawn_helper_delete (backend_spawn); + pk_backend_error_code (backend_spawn->priv->backend, PK_ERROR_ENUM_INTERNAL_ERROR, +diff --git a/src/pk-backend.c b/src/pk-backend.c +index 225c488..37ed024 100644 +--- a/src/pk-backend.c ++++ b/src/pk-backend.c +@@ -33,6 +33,7 @@ + #include <glib/gprintf.h> + #include <pk-network.h> + ++#include "pk-package-item.h" + #include "pk-debug.h" + #include "pk-common.h" + #include "pk-marshal.h" +@@ -44,13 +45,6 @@ + #define PK_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PK_TYPE_BACKEND, PkBackendPrivate)) + + /** +- * PK_BACKEND_PERCENTAGE_INVALID: +- * +- * The unknown percentage value +- */ +-#define PK_BACKEND_PERCENTAGE_INVALID 101 +- +-/** + * PK_BACKEND_PERCENTAGE_DEFAULT: + * + * The default percentage value, should never be emitted, but should be +@@ -84,12 +78,15 @@ struct _PkBackendPrivate + GHashTable *eulas; + gchar *name; + gchar *c_tid; ++ gchar *proxy_http; ++ gchar *proxy_ftp; + gboolean locked; + gboolean set_error; + gboolean set_signature; + gboolean set_eula; + gboolean has_sent_package; + PkNetwork *network; ++ PkPackageItem *last_package; + PkRoleEnum role; /* this never changes for the lifetime of a transaction */ + PkStatusEnum status; /* this changes */ + PkExitEnum exit; +@@ -592,6 +589,44 @@ out: + } + + /** ++ * pk_backend_set_proxy: ++ **/ ++gboolean ++pk_backend_set_proxy (PkBackend *backend, const gchar *proxy_http, const gchar *proxy_ftp) ++{ ++ g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE); ++ g_free (backend->priv->proxy_http); ++ g_free (backend->priv->proxy_ftp); ++ backend->priv->proxy_http = g_strdup (proxy_http); ++ backend->priv->proxy_ftp = g_strdup (proxy_ftp); ++ return TRUE; ++} ++ ++/** ++ * pk_backend_get_proxy_http: ++ * ++ * Return value: proxy string in the form username:password@server:port ++ **/ ++gchar * ++pk_backend_get_proxy_http (PkBackend *backend) ++{ ++ g_return_val_if_fail (PK_IS_BACKEND (backend), NULL); ++ return g_strdup (backend->priv->proxy_http); ++} ++ ++/** ++ * pk_backend_get_proxy_ftp: ++ * ++ * Return value: proxy string in the form username:password@server:port ++ **/ ++gchar * ++pk_backend_get_proxy_ftp (PkBackend *backend) ++{ ++ g_return_val_if_fail (PK_IS_BACKEND (backend), NULL); ++ return g_strdup (backend->priv->proxy_ftp); ++} ++ ++/** + * pk_backend_lock: + * + * Responsible for initialising the external backend object. +@@ -803,35 +838,6 @@ pk_backend_set_sub_percentage (PkBackend *backend, guint percentage) + } + + /** +- * pk_backend_no_percentage_updates: +- **/ +-gboolean +-pk_backend_no_percentage_updates (PkBackend *backend) +-{ +- g_return_val_if_fail (PK_IS_BACKEND (backend), 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; +- } +- +- /* set the same twice? */ +- if (backend->priv->last_percentage == PK_BACKEND_PERCENTAGE_INVALID) { +- pk_debug ("duplicate set of %i", PK_BACKEND_PERCENTAGE_INVALID); +- return FALSE; +- } +- +- /* invalidate previous percentage */ +- backend->priv->last_percentage = PK_BACKEND_PERCENTAGE_INVALID; +- +- /* emit the progress changed signal */ +- pk_backend_emit_progress_changed (backend); +- return TRUE; +-} +- +-/** + * pk_backend_set_status: + **/ + gboolean +@@ -901,11 +907,26 @@ gboolean + pk_backend_package (PkBackend *backend, PkInfoEnum info, const gchar *package_id, const gchar *summary) + { + gchar *summary_safe; ++ PkPackageItem *item; ++ gboolean ret; + + g_return_val_if_fail (PK_IS_BACKEND (backend), FALSE); + g_return_val_if_fail (package_id != NULL, FALSE); + g_return_val_if_fail (backend->priv->locked != FALSE, FALSE); + ++ /* check against the old one */ ++ item = pk_package_item_new (info, package_id, summary); ++ ret = pk_package_item_equal (item, backend->priv->last_package); ++ if (ret) { ++ pk_package_item_free (item); ++ pk_debug ("skipping duplicate %s", package_id); ++ return FALSE; ++ } ++ /* update the 'last' package */ ++ pk_package_item_free (backend->priv->last_package); ++ backend->priv->last_package = pk_package_item_copy (item); ++ pk_package_item_free (item); ++ + /* have we already set an error? */ + if (backend->priv->set_error) { + pk_warning ("already set error, cannot process"); +@@ -1689,6 +1710,8 @@ pk_backend_finalize (GObject *object) + pk_debug ("backend finalise"); + + pk_backend_reset (backend); ++ g_free (backend->priv->proxy_http); ++ g_free (backend->priv->proxy_ftp); + g_free (backend->priv->name); + g_free (backend->priv->c_tid); + g_object_unref (backend->priv->time); +@@ -1818,6 +1841,7 @@ pk_backend_reset (PkBackend *backend) + + /* TODO: need to wait for Finished() if running */ + ++ pk_package_item_free (backend->priv->last_package); + backend->priv->set_error = FALSE; + backend->priv->set_signature = FALSE; + backend->priv->set_eula = FALSE; +@@ -1825,6 +1849,7 @@ pk_backend_reset (PkBackend *backend) + backend->priv->finished = FALSE; + backend->priv->has_sent_package = FALSE; + backend->priv->thread = NULL; ++ backend->priv->last_package = NULL; + backend->priv->status = PK_STATUS_ENUM_UNKNOWN; + backend->priv->exit = PK_EXIT_ENUM_UNKNOWN; + backend->priv->role = PK_ROLE_ENUM_UNKNOWN; +@@ -1855,8 +1880,11 @@ pk_backend_init (PkBackend *backend) + backend->priv->handle = NULL; + backend->priv->name = NULL; + backend->priv->c_tid = NULL; ++ backend->priv->proxy_http = NULL; ++ backend->priv->proxy_ftp = NULL; + backend->priv->file_changed_func = NULL; + backend->priv->file_changed_data = NULL; ++ backend->priv->last_package = NULL; + backend->priv->locked = FALSE; + backend->priv->signal_finished = 0; + backend->priv->signal_error_timeout = 0; +diff --git a/src/pk-backend.h b/src/pk-backend.h +index 95b7fa8..fb17e3c 100644 +--- a/src/pk-backend.h ++++ b/src/pk-backend.h +@@ -30,6 +30,13 @@ + + G_BEGIN_DECLS + ++/** ++ * PK_BACKEND_PERCENTAGE_INVALID: ++ * ++ * The unknown percentage value ++ */ ++#define PK_BACKEND_PERCENTAGE_INVALID 101 ++ + typedef struct _PkBackend PkBackend; + + /* set the state */ +@@ -51,7 +58,6 @@ gboolean pk_backend_set_sub_percentage (PkBackend *backend, + guint percentage); + gboolean pk_backend_set_exit_code (PkBackend *backend, + PkExitEnum exit); +-gboolean pk_backend_no_percentage_updates (PkBackend *backend); + gboolean pk_backend_set_transaction_data (PkBackend *backend, + const gchar *data); + +@@ -66,6 +72,8 @@ gboolean pk_backend_get_progress (PkBackend *backend, + guint *elapsed, + guint *remaining); + guint pk_backend_get_runtime (PkBackend *backend); ++gchar *pk_backend_get_proxy_ftp (PkBackend *backend); ++gchar *pk_backend_get_proxy_http (PkBackend *backend); + + /* signal helpers */ + gboolean pk_backend_finished (PkBackend *backend); +diff --git a/src/pk-engine.c b/src/pk-engine.c +index db81d36..028a0d0 100644 +--- a/src/pk-engine.c ++++ b/src/pk-engine.c +@@ -101,6 +101,7 @@ struct PkEnginePrivate + PkNetwork *network; + PkSecurity *security; + PkNotify *notify; ++ PkConf *conf; + PkFileMonitor *file_monitor; + PkRoleEnum actions; + PkGroupEnum groups; +@@ -579,10 +580,15 @@ pk_engine_init (PkEngine *engine) + DBusGConnection *connection; + gboolean ret; + gchar *filename; ++ gchar *proxy_http; ++ gchar *proxy_ftp; + + engine->priv = PK_ENGINE_GET_PRIVATE (engine); + engine->priv->restart_schedule = FALSE; + ++ /* use the config file */ ++ engine->priv->conf = pk_conf_new (); ++ + /* setup the backend backend */ + engine->priv->backend = pk_backend_new (); + g_signal_connect (engine->priv->backend, "finished", +@@ -639,6 +645,13 @@ pk_engine_init (PkEngine *engine) + G_CALLBACK (pk_engine_file_monitor_changed_cb), engine); + g_free (filename); + ++ /* set the proxy */ ++ proxy_http = pk_conf_get_string (engine->priv->conf, "ProxyHTTP"); ++ proxy_ftp = pk_conf_get_string (engine->priv->conf, "ProxyFTP"); ++ pk_backend_set_proxy (engine->priv->backend, proxy_http, proxy_ftp); ++ g_free (proxy_http); ++ g_free (proxy_ftp); ++ + engine->priv->transaction_list = pk_transaction_list_new (); + g_signal_connect (engine->priv->transaction_list, "changed", + G_CALLBACK (pk_engine_transaction_list_changed_cb), engine); +@@ -696,6 +709,7 @@ pk_engine_finalize (GObject *object) + g_object_unref (engine->priv->notify); + g_object_unref (engine->priv->backend); + g_object_unref (engine->priv->cache); ++ g_object_unref (engine->priv->conf); + + G_OBJECT_CLASS (pk_engine_parent_class)->finalize (object); + } +diff --git a/src/pk-network-unix.c b/src/pk-network-unix.c +index 11c23a2..74b266c 100644 +--- a/src/pk-network-unix.c ++++ b/src/pk-network-unix.c +@@ -138,6 +138,11 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix) + continue; + } + ++ /* is loopback? */ ++ if (pk_strequal (sections[0], "lo")) { ++ continue; ++ } ++ + /* is correct parameters? */ + number_sections = g_strv_length (sections); + if (number_sections != 11) { +@@ -145,9 +150,8 @@ pk_network_unix_get_network_state (PkNetworkUnix *network_unix) + continue; + } + +- /* is MTU and gateway nonzero? */ +- if (!pk_strequal (sections[8], "0") && +- !pk_strequal (sections[2], "00000000")) { ++ /* is gateway nonzero? */ ++ if (!pk_strequal (sections[2], "00000000")) { + pk_debug ("interface %s is valid", sections[0]); + online = TRUE; + } +diff --git a/src/pk-network.c b/src/pk-network.c +index 9656958..0ad839e 100644 +--- a/src/pk-network.c ++++ b/src/pk-network.c +@@ -39,6 +39,7 @@ + #ifdef HAVE_UNISTD_H + #include <unistd.h> + #endif /* HAVE_UNISTD_H */ ++#include <libgbus.h> + + #include <glib/gi18n.h> + +@@ -67,6 +68,7 @@ struct _PkNetworkPrivate + PkNetworkNm *net_nm; + PkNetworkUnix *net_unix; + PkConf *conf; ++ LibGBus *nm_bus; + }; + + enum { +@@ -154,6 +156,7 @@ pk_network_class_init (PkNetworkClass *klass) + static void + pk_network_init (PkNetwork *network) + { ++ gboolean nm_alive; + network->priv = PK_NETWORK_GET_PRIVATE (network); + network->priv->conf = pk_conf_new (); + network->priv->net_nm = pk_network_nm_new (); +@@ -167,6 +170,17 @@ pk_network_init (PkNetwork *network) + network->priv->use_nm = pk_conf_get_bool (network->priv->conf, "UseNetworkManager"); + network->priv->use_unix = pk_conf_get_bool (network->priv->conf, "UseNetworkHeuristic"); + ++ /* check if NM is on the bus */ ++ network->priv->nm_bus = libgbus_new (); ++ libgbus_assign (network->priv->nm_bus, LIBGBUS_SYSTEM, "org.freedesktop.NetworkManager"); ++ nm_alive = libgbus_is_connected (network->priv->nm_bus); ++ ++ /* NetworkManager isn't up, so we can't use it */ ++ if (network->priv->use_nm && !nm_alive) { ++ pk_warning ("UseNetworkManager true, but org.freedesktop.NetworkManager not up"); ++ network->priv->use_nm = FALSE; ++ } ++ + #if !PK_BUILD_NETWORKMANAGER + /* check we can actually use the default */ + if (network->priv->use_nm) { +@@ -190,6 +204,7 @@ pk_network_finalize (GObject *object) + + g_return_if_fail (network->priv != NULL); + g_object_unref (network->priv->conf); ++ g_object_unref (network->priv->nm_bus); + g_object_unref (network->priv->net_nm); + g_object_unref (network->priv->net_unix); + G_OBJECT_CLASS (pk_network_parent_class)->finalize (object); +diff --git a/src/pk-spawn.c b/src/pk-spawn.c +index 9b415b1..c4622f9 100644 +--- a/src/pk-spawn.c ++++ b/src/pk-spawn.c +@@ -273,7 +273,7 @@ pk_spawn_kill (PkSpawn *spawn) + * + **/ + gboolean +-pk_spawn_argv (PkSpawn *spawn, gchar **argv) ++pk_spawn_argv (PkSpawn *spawn, gchar **argv, gchar **envp) + { + gboolean ret; + +@@ -284,7 +284,7 @@ pk_spawn_argv (PkSpawn *spawn, gchar **argv) + spawn->priv->finished = FALSE; + + /* create spawned object for tracking */ +- ret = g_spawn_async_with_pipes (NULL, argv, NULL, ++ ret = g_spawn_async_with_pipes (NULL, argv, envp, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, + NULL, NULL, &spawn->priv->child_pid, + NULL, /* stdin */ +@@ -484,6 +484,7 @@ libst_spawn (LibSelfTest *test) + gboolean ret; + gchar *path; + gchar **argv; ++ gchar **envp; + + if (libst_start (test, "PkSpawn", CLASS_AUTO) == FALSE) { + return; +@@ -496,7 +497,7 @@ libst_spawn (LibSelfTest *test) + libst_title (test, "make sure return error for missing file"); + mexit = BAD_EXIT; + argv = g_strsplit ("pk-spawn-test-xxx.sh", " ", 0); +- ret = pk_spawn_argv (spawn, argv); ++ ret = pk_spawn_argv (spawn, argv, NULL); + g_strfreev (argv); + if (ret == FALSE) { + libst_success (test, "failed to run invalid file"); +@@ -517,7 +518,7 @@ libst_spawn (LibSelfTest *test) + mexit = -1; + path = pk_test_get_data ("pk-spawn-test.sh"); + argv = g_strsplit (path, " ", 0); +- ret = pk_spawn_argv (spawn, argv); ++ ret = pk_spawn_argv (spawn, argv, NULL); + g_free (path); + g_strfreev (argv); + if (ret) { +@@ -558,11 +559,34 @@ libst_spawn (LibSelfTest *test) + new_spawn_object (test, &spawn); + + /************************************************************/ ++ libst_title (test, "make sure we set the proxy"); ++ mexit = -1; ++ path = pk_test_get_data ("pk-spawn-proxy.sh"); ++ argv = g_strsplit (path, " ", 0); ++ envp = g_strsplit ("http_proxy=username:password@server:port " ++ "ftp_proxy=username:password@server:port", " ", 0); ++ ret = pk_spawn_argv (spawn, argv, envp); ++ g_free (path); ++ g_strfreev (argv); ++ if (ret) { ++ libst_success (test, "ran correct file"); ++ } else { ++ libst_failed (test, "did not run helper"); ++ } ++ ++ /* wait for finished */ ++ libst_loopwait (test, 10000); ++ libst_loopcheck (test); ++ ++ /* get new object */ ++ new_spawn_object (test, &spawn); ++ ++ /************************************************************/ + libst_title (test, "make sure run correct helper, and kill it"); + mexit = BAD_EXIT; + path = pk_test_get_data ("pk-spawn-test.sh"); + argv = g_strsplit (path, " ", 0); +- ret = pk_spawn_argv (spawn, argv); ++ ret = pk_spawn_argv (spawn, argv, NULL); + g_free (path); + g_strfreev (argv); + if (ret) { +@@ -592,7 +616,7 @@ libst_spawn (LibSelfTest *test) + mexit = BAD_EXIT; + path = pk_test_get_data ("pk-spawn-test-sigquit.sh"); + argv = g_strsplit (path, " ", 0); +- ret = pk_spawn_argv (spawn, argv); ++ ret = pk_spawn_argv (spawn, argv, NULL); + g_free (path); + g_strfreev (argv); + if (ret) { +@@ -618,7 +642,7 @@ libst_spawn (LibSelfTest *test) + libst_title (test, "run lots of data for profiling"); + path = pk_test_get_data ("pk-spawn-test-profiling.sh"); + argv = g_strsplit (path, " ", 0); +- ret = pk_spawn_argv (spawn, argv); ++ ret = pk_spawn_argv (spawn, argv, NULL); + g_free (path); + g_strfreev (argv); + if (ret) { +diff --git a/src/pk-spawn.h b/src/pk-spawn.h +index 1b20fef..0e58859 100644 +--- a/src/pk-spawn.h ++++ b/src/pk-spawn.h +@@ -52,7 +52,8 @@ GType pk_spawn_get_type (void) G_GNUC_CONST; + PkSpawn *pk_spawn_new (void); + + gboolean pk_spawn_argv (PkSpawn *spawn, +- gchar **argv) ++ gchar **argv, ++ gchar **envp) + G_GNUC_WARN_UNUSED_RESULT; + gboolean pk_spawn_kill (PkSpawn *spawn); + |