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

Richard Hughes hughsient at kemper.freedesktop.org
Mon Feb 23 02:35:43 PST 2009


 NEWS                                                 |   81 
 RELEASE                                              |    4 
 backends/apt/Makefile.am                             |    8 
 backends/apt/aptDBUSBackend.py                       | 2234 -------------------
 backends/apt/aptbackend.py                           | 2187 ++++++++++++++++++
 backends/apt/debfile.py                              |  536 ----
 backends/apt/pk-backend-apt.py                       |   28 
 backends/apt/update-packagekit-app-data              |   86 
 backends/conary/Makefile.am                          |    5 
 backends/conary/conaryBackend.py                     |   48 
 backends/conary/conaryCallback.py                    |  380 ++-
 backends/conary/conaryEnums.py                       |  121 +
 backends/conary/conaryFilter.py                      |    3 
 backends/conary/conaryProgress.py                    |  105 
 backends/conary/conarypk.py                          |    1 
 backends/zypp/zypp-events.h                          |   20 
 client/pk-console.c                                  |    7 
 client/pk-tools-common.c                             |   15 
 configure.ac                                         |    9 
 contrib/Makefile.am                                  |    4 
 contrib/app-install/.gitignore                       |    7 
 contrib/app-install/Makefile.am                      |   55 
 contrib/app-install/egg-debug.c                      |    1 
 contrib/app-install/egg-debug.h                      |    1 
 contrib/app-install/pk-app-install-add.c             |  345 ++
 contrib/app-install/pk-app-install-common.h          |   33 
 contrib/app-install/pk-app-install-create.c          |  132 +
 contrib/app-install/pk-app-install-generate.c        |  345 ++
 contrib/app-install/pk-app-install-remove.c          |  195 +
 data/org.freedesktop.PackageKitAptBackend.service.in |    2 
 docs/api/spec/pk-introduction.xml                    |    6 
 docs/app-install-v1.draft                            |   21 
 docs/html/pk-download.html                           |    1 
 po/POTFILES.in                                       |    4 
 po/es.po                                             |  868 +++----
 po/pl.po                                             |  468 ++-
 po/pt_BR.po                                          |   89 
 po/zh_CN.po                                          |  778 +++---
 38 files changed, 5334 insertions(+), 3899 deletions(-)

New commits:
commit 6427e3ba187201fbda49febe48313f1ad64d0425
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Feb 23 10:34:43 2009 +0000

    Release version 0.4.4

diff --git a/NEWS b/NEWS
index e615a0f..2ab0e35 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,84 @@
+Version 0.4.4
+~~~~~~~~~~~~~
+Released: 2009-02-23
+
+Translations:
+ - Updated Swedish translation (Daniel Nylander)
+ - Updated Spanish translation (Domingo Becker)
+ - Updated German translation (Fabian Affolter)
+ - Updated Brazilian Portuguese translation (Igor Pires Soares)
+ - Updated Polish translation (Piotr DrÄ…g)
+ - Updated Simplified Chinese translation (zhourongrong)
+
+New Features:
+ - Add a new method GetDaemonState to the main interface to help debugging on
+   live systems (Richard Hughes)
+ - Print the daemon state when using pkmon in verbose mode (Richard Hughes)
+ - Add a draft standard for application install metadata handling (Richard Hughes)
+ - Add a pk-app-install binary for manipulating the sqlite cache (Richard Hughes)
+ - PackageKit-Qt: Sync API for RequireRestart (Adrien BUSTANY)
+ - PackageKit-Qt: Add support for application filter (Adrien BUSTANY)
+ - PackageKit-Qt: Add a searchFromDesktopFile method  (Adrien BUSTANY)
+
+Bugfixes:
+ - Updated documentation with UseSyslog parameter (Balaji)
+ - Fix for the updates and obsoletes delimiter (Daniel Nicoletti)
+ - Make the dbus policy more fine grained (Sebastian Heinlein)
+ - Fix compile failure with gcc-4.4.0 and old versions of glib2 (Richard Hughes)
+ - If we fail to exit from the dispatcher, make sure we cleanup the poll as the
+   child check isn't going to be run (Richard Hughes)
+ - The QT lib now depends on QtSql, so add this to the configure (Richard Hughes)
+ - Fix up resolve in pkcon and from libpackagekit-glib (Richard Hughes)
+ - Don't dereference a NULL pointer in pk_console_resolve() which can be done
+   using pkcon list-install (Richard Hughes)
+ - Don't use an local error in pkcon list-install else we'll fail to free it,
+   and it's non-fatal (Richard Hughes)
+ - PackageKit-Qt: Handle daemon errors more gracefully (Adrien BUSTANY)
+ - PackageKit-Qt: Add a getLastError method to get the last daemon error (Adrien BUSTANY)
+ - PackageKit-Qt: Add missing implementation for uid and cmdline (Adrien BUSTANY)
+ - Packagekit-Qt: Fix to make what provides work (Daniel Nicoletti)
+
+Backends:
+ - alpm: Added experimental support for progress indication (Valeriy Lyasotskiy)
+ - alpm: Updated alpm backend status in status matrix (Valeriy Lyasotskiy)
+ - apt: Allow the properties and introspection interface of the backend
+        to everyone (Sebastian Heinlein)
+ - apt: Use the merged debfile module of python-apt (Sebastian Heinlein)
+ - apt: Fix an API change in debfile (Sebastian Heinlein)
+ - apt: Install the main Python module into the packagekit package and use a command
+        wrapper to improve the start time (*.pyc) (Sebastian Heinlein)
+ - apt: Remove code which is now merged with python-apt (Sebastian Heinlein)
+ - apt: Add script to extract information from app-install desktop files (Sebastian Heinlein)
+ - conary: Fix get-updates command (Andres Vargas)
+ - conary: Fix the group search (Andres Vargas)
+ - conary: Change the error signal for groups not found (Andres Vargas)
+ - conary: Add a percent progress on install packages (Andres Vargas)
+ - conary: Remove the subpercent signal only percent signal (Andres Vargas)
+ - conary: Add subpercent for minitasks (Andres Vargas)
+ - conary: Tuning the percent update (Andres Vargas)
+ - conary: Fix step feeling for percent download (Andres Vargas)
+ - conary: Add percent to update/remove/get-updates/update-system (Andres Vargas)
+ - conary: Add a exception for run get-updates first and then update (Andres Vargas)
+ - conary: update-system do a stepdown percent (Andres Vargas)
+ - conary: Fix the search ~installed filter (Andres Vargas)
+ - conary: Add more classify groups (Andres Vargas)
+ - conary: Implement the conaryEnums for classify category in groups fix the
+           backend for search groups (Andres Vargas)
+ - conary: Add more log info to callbacks fix get-files (Andres Vargas)
+ - conary: Fix get-files from many troves (Andres Vargas)
+ - dummy: Use the correct delimiter for the obsoletes in the kernel package (Richard Hughes)
+ - dummy: Add update detail for the blocked package, and raise an error
+          if we can't find a match (Richard Hughes)
+ - dummy: Add a simple rollback action (Richard Hughes)
+ - poldek: Build fix (Patryk Zawadzki)
+ - poldek: For NOT_INSTALLED filter return only available packages that are NOT
+           installed (Marcin Banasiak)
+ - yum: Adds an auto_close attribute to the rpmdb object (Seth Vidal)
+ - yum: Add support for the new font and mimehandler provides (Richard Hughes)
+ - yum: Don't backtrace with an internal error when the filename is not
+        unicode. Fixes rh#480440 (Richard Hughes)
+ - zypp: Fix up virtual callback methods (Scott Reeves)
+
 Version 0.4.3
 ~~~~~~~~~~~~~
 Released: 2009-02-02
diff --git a/RELEASE b/RELEASE
index ea39f5a..90b9d07 100644
--- a/RELEASE
+++ b/RELEASE
@@ -3,8 +3,8 @@ PackageKit Release Notes
 1. Write NEWS entries for PackageKit and gnome-packagekit in the same
    format as usual. Ignore any trivial commits.
 
-git-shortlog PACKAGEKIT_0_4_3.. | grep -v trivial | grep -v Merge > NEWS.new
-git-shortlog GNOME_PACKAGEKIT_0_4_3.. | grep -v trivial | grep -v Merge > NEWS.new
+git shortlog PACKAGEKIT_0_4_3.. | grep -v trivial | grep -v Merge > NEWS.new
+git shortlog GNOME_PACKAGEKIT_0_4_3.. | grep -v trivial | grep -v Merge > NEWS.new
 
 2. Add download date to docs/html/pk-download.html, save file.
 
diff --git a/docs/html/pk-download.html b/docs/html/pk-download.html
index 7c1451f..7b30a44 100644
--- a/docs/html/pk-download.html
+++ b/docs/html/pk-download.html
@@ -68,6 +68,7 @@ Releases are normally once every 1-2 weeks.
 </p>
 <table>
 <tr><td><b>Version</b></td><td>&nbsp;&nbsp;</td><td><b>Date</b></td></tr>
+<tr><td>0.4.4</td><td></td><td>2009-02-23</td></tr>
 <tr><td>0.4.3</td><td></td><td>2009-02-02</td></tr>
 <tr><td>0.4.2</td><td></td><td>2009-01-19</td></tr>
 <tr><td>0.4.1</td><td></td><td>2009-01-08</td></tr>
commit dce120bfd93e0f1764c224a55b84898f70e5277c
Merge: 60762c8... fb5748c...
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Feb 23 10:33:15 2009 +0000

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

commit fb5748cfcd25e626937d14130691e8ecb66c4856
Merge: 32fdfa9... 5d60f24...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 23 11:33:35 2009 +0100

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

commit 32fdfa9cc18245c822cb1d132020cea81be9ff19
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 23 11:32:38 2009 +0100

    AppInst: Rename repo_name to repo_id since it makes sense to follow the PackageKit naming

diff --git a/contrib/app-install/pk-app-install-create.c b/contrib/app-install/pk-app-install-create.c
index 1f57cc2..db2c86e 100644
--- a/contrib/app-install/pk-app-install-create.c
+++ b/contrib/app-install/pk-app-install-create.c
@@ -102,7 +102,7 @@ main (int argc, char *argv[])
 			    "application_id TEXT primary key,"
 			    "package_name TEXT,"
 			    "group_id TEXT,"
-			    "repo_name TEXT,"
+			    "repo_id TEXT,"
 			    "application_name TEXT,"
 			    "application_summary TEXT);";
 		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
diff --git a/contrib/app-install/pk-app-install-remove.c b/contrib/app-install/pk-app-install-remove.c
index 9c1c408..2ce8b71 100644
--- a/contrib/app-install/pk-app-install-remove.c
+++ b/contrib/app-install/pk-app-install-remove.c
@@ -142,7 +142,7 @@ main (int argc, char *argv[])
 	}
 
 	/* remove icons */
-	statement = g_strdup_printf ("SELECT application_id FROM applications WHERE repo_name = '%s'", repo);
+	statement = g_strdup_printf ("SELECT application_id FROM applications WHERE repo_id = '%s'", repo);
 	rc = sqlite3_exec (db, statement, pk_app_install_remove_icons_sqlite_cb, (void*) icondir, &error_msg);
 	g_free (statement);
 	if (rc != SQLITE_OK) {
@@ -151,10 +151,10 @@ main (int argc, char *argv[])
 		return 0;
 	}
 
-	/* delete from translations (translations has no repo_name, so key of applications) */
+	/* delete from translations (translations has no repo_id, so key of applications) */
 	statement = g_strdup_printf ("DELETE FROM translations WHERE EXISTS ( "
 				      "SELECT applications.application_id FROM applications WHERE "
-				      "applications.application_id = applications.application_id AND applications.repo_name = '%s')", repo);
+				      "applications.application_id = applications.application_id AND applications.repo_id = '%s')", repo);
 	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
 	g_free (statement);
 	if (rc) {
@@ -165,7 +165,7 @@ main (int argc, char *argv[])
 	egg_debug ("%i removals from translations", sqlite3_changes (db));
 
 	/* delete from applications */
-	statement = g_strdup_printf ("DELETE FROM applications WHERE repo_name = '%s'", repo);
+	statement = g_strdup_printf ("DELETE FROM applications WHERE repo_id = '%s'", repo);
 	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
 	g_free (statement);
 	if (rc) {
commit 5a9d1bbc03ad0f36ab50ca346180df49014ec71f
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 23 11:32:01 2009 +0100

    AppInst: Update draft to adapt name changes

diff --git a/docs/app-install-v1.draft b/docs/app-install-v1.draft
index 08d4e58..65252fd 100644
--- a/docs/app-install-v1.draft
+++ b/docs/app-install-v1.draft
@@ -77,17 +77,17 @@ This is used, for instance:
 
 == Schema ==
 
-TABLE localised:
+TABLE translations:
 STRING application_id (name of the desktop file, with no extension)
 STRING application_name (Name in desktop file, in locale)
 STRING application_summary (Comment in desktop file, in locale)
 STRING locale
 
-TABLE general
+TABLE applications:
 STRING application_id (name of the desktop file, with no extension)
 STRING package_name (the package name, e.g. 'nautilus')
-STRING group_id (Categories from desktop file, _not_ PK groups or PK categories)
-STRING repo_name (for adding and removal)
+STRING categories (Categories from desktop file, _not_ PK groups or PK categories)
+STRING repo_id (for adding and removal)
 STRING application_name (Name in desktop file)
 STRING application_summary (Comment in desktop file)
 
commit 57e4eafee993b92489c1f1926b6f9068cb20145e
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 23 11:29:52 2009 +0100

    App-Inst: Rename table general to applications and localised to translations

diff --git a/contrib/app-install/pk-app-install-create.c b/contrib/app-install/pk-app-install-create.c
index cfb3b34..1f57cc2 100644
--- a/contrib/app-install/pk-app-install-create.c
+++ b/contrib/app-install/pk-app-install-create.c
@@ -98,7 +98,7 @@ main (int argc, char *argv[])
 
 	/* create */
 	if (create_file == FALSE) {
-		statement = "CREATE TABLE general ("
+		statement = "CREATE TABLE applications ("
 			    "application_id TEXT primary key,"
 			    "package_name TEXT,"
 			    "group_id TEXT,"
@@ -107,18 +107,18 @@ main (int argc, char *argv[])
 			    "application_summary TEXT);";
 		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
 		if (rc) {
-			egg_warning ("Can't create general table: %s\n", sqlite3_errmsg (db));
+			egg_warning ("Can't create applications table: %s\n", sqlite3_errmsg (db));
 			retval = 1;
 			goto out;
 		}
-		statement = "CREATE TABLE localised ("
+		statement = "CREATE TABLE translations ("
 			    "application_id TEXT,"
 			    "application_name TEXT,"
 			    "application_summary TEXT,"
 			    "locale TEXT);";
 		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
 		if (rc) {
-			egg_warning ("Can't create localised table: %s\n", sqlite3_errmsg (db));
+			egg_warning ("Can't create translations table: %s\n", sqlite3_errmsg (db));
 			retval = 1;
 			goto out;
 		}
diff --git a/contrib/app-install/pk-app-install-remove.c b/contrib/app-install/pk-app-install-remove.c
index d5f3070..9c1c408 100644
--- a/contrib/app-install/pk-app-install-remove.c
+++ b/contrib/app-install/pk-app-install-remove.c
@@ -142,7 +142,7 @@ main (int argc, char *argv[])
 	}
 
 	/* remove icons */
-	statement = g_strdup_printf ("SELECT application_id FROM general WHERE repo_name = '%s'", repo);
+	statement = g_strdup_printf ("SELECT application_id FROM applications WHERE repo_name = '%s'", repo);
 	rc = sqlite3_exec (db, statement, pk_app_install_remove_icons_sqlite_cb, (void*) icondir, &error_msg);
 	g_free (statement);
 	if (rc != SQLITE_OK) {
@@ -151,10 +151,10 @@ main (int argc, char *argv[])
 		return 0;
 	}
 
-	/* delete from localised (localised has no repo_name, so key off general) */
-	statement = g_strdup_printf ("DELETE FROM localised WHERE EXISTS ( "
-				      "SELECT general.application_id FROM general WHERE "
-				      "general.application_id = general.application_id AND general.repo_name = '%s')", repo);
+	/* delete from translations (translations has no repo_name, so key of applications) */
+	statement = g_strdup_printf ("DELETE FROM translations WHERE EXISTS ( "
+				      "SELECT applications.application_id FROM applications WHERE "
+				      "applications.application_id = applications.application_id AND applications.repo_name = '%s')", repo);
 	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
 	g_free (statement);
 	if (rc) {
@@ -162,10 +162,10 @@ main (int argc, char *argv[])
 		ret = FALSE;
 		goto out;
 	}
-	egg_debug ("%i removals from localised", sqlite3_changes (db));
+	egg_debug ("%i removals from translations", sqlite3_changes (db));
 
-	/* delete from general */
-	statement = g_strdup_printf ("DELETE FROM general WHERE repo_name = '%s'", repo);
+	/* delete from applications */
+	statement = g_strdup_printf ("DELETE FROM applications WHERE repo_name = '%s'", repo);
 	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
 	g_free (statement);
 	if (rc) {
@@ -173,7 +173,7 @@ main (int argc, char *argv[])
 		ret = FALSE;
 		goto out;
 	}
-	egg_debug ("%i removals from general", sqlite3_changes (db));
+	egg_debug ("%i removals from applications", sqlite3_changes (db));
 
 	/* reclaim memory */
 	statement = g_strdup ("VACUUM");
commit 60762c854b26fa00724217a2631e9429db163441
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Feb 23 10:28:31 2009 +0000

    trivial: build new files

diff --git a/contrib/app-install/Makefile.am b/contrib/app-install/Makefile.am
index c76b7d5..9d39362 100644
--- a/contrib/app-install/Makefile.am
+++ b/contrib/app-install/Makefile.am
@@ -13,6 +13,8 @@ INCLUDES =						\
 	-DEGG_CONSOLE="\"PK_CONSOLE\""			\
 	-I$(top_srcdir)/lib
 
+noinst_PROGRAMS = pk-app-install-add pk-app-install-generate
+
 sbin_PROGRAMS = pk-app-install-create pk-app-install-remove
 
 pk_app_install_create_SOURCES =				\
@@ -33,3 +35,21 @@ pk_app_install_remove_SOURCES =				\
 pk_app_install_remove_LDADD = $(GLIB_LIBS) $(SQLITE_LIBS)
 pk_app_install_remove_CFLAGS = $(WARNINGFLAGS_C)
 
+pk_app_install_add_SOURCES =				\
+	egg-debug.c					\
+	egg-debug.h					\
+	pk-app-install-add.c				\
+	pk-app-install-common.h				\
+	$(NULL)
+pk_app_install_add_LDADD = $(GLIB_LIBS) $(SQLITE_LIBS)
+pk_app_install_add_CFLAGS = $(WARNINGFLAGS_C)
+
+pk_app_install_generate_SOURCES =			\
+	egg-debug.c					\
+	egg-debug.h					\
+	pk-app-install-generate.c			\
+	pk-app-install-common.h				\
+	$(NULL)
+pk_app_install_generate_LDADD = $(GLIB_LIBS) $(SQLITE_LIBS)
+pk_app_install_generate_CFLAGS = $(WARNINGFLAGS_C)
+
commit 5d60f2494c8c07df4434db6842245d13de968869
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Feb 23 09:14:32 2009 +0000

    trivial: fix build

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9887fec..c760546 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,6 +7,10 @@ client/pk-monitor.c
 client/pk-tools-common.c
 contrib/command-not-found/pk-command-not-found.c
 contrib/browser-plugin/src/contents.cpp
+contrib/app-install/pk-app-install-add.c
+contrib/app-install/pk-app-install-create.c
+contrib/app-install/pk-app-install-generate.c
+contrib/app-install/pk-app-install-remove.c
 data/packagekit-catalog.xml.in
 data/packagekit-package-list.xml.in
 data/packagekit-servicepack.xml.in
commit d98abbf4ace236db09f34c6aea8ca04c8bf61fb9
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Sun Feb 22 23:21:35 2009 -0600

    conary: add more classify groups

diff --git a/backends/conary/conaryEnums.py b/backends/conary/conaryEnums.py
index 6584ddd..1089f02 100644
--- a/backends/conary/conaryEnums.py
+++ b/backends/conary/conaryEnums.py
@@ -54,6 +54,127 @@ categoryMap = {
 'Utility': GROUP_ACCESSORIES,
 'GUIDesigner': GROUP_PROGRAMMING,
 'TerminalEmulator': GROUP_ACCESSORIES,
+'Video': GROUP_MULTIMEDIA ,
+'Education': GROUP_EDUCATION,
+'Game': GROUP_GAMES ,
+'Building': GROUP_PROGRAMMING,
+'Debugger': GROUP_PROGRAMMING,
+'IDE': GROUP_PROGRAMMING,
+'GUIDesigner': GROUP_PROGRAMMING,
+'Profiling': GROUP_PROGRAMMING,
+'RevisionControl': GROUP_PROGRAMMING, #	Applications like cvs or subversion	Development
+'Database': GROUP_PROGRAMMING, #	Application to manage a database	Office or Development or AudioVideo
+'Translation': GROUP_PROGRAMMING,#	A translation tool	Development
+'Calendar': GROUP_OFFICE,#	Calendar application	Office
+'ContactManagement':GROUP_OFFICE,#	E.g. an address book	Office
+'Dictionary': GROUP_OFFICE,#	A dictionary	Office;TextTools
+'Chart': GROUP_OFFICE,#	Chart application	Office
+'Finance':GROUP_OFFICE,#	Application to manage your finance	Office
+'FlowChart': GROUP_OFFICE,#	A flowchart application	Office
+'PDA': GROUP_OFFICE, #	Tool to manage your PDA	Office
+'ProjectManagement': GROUP_OFFICE,#	Project management application	Office;Development
+'Presentation': GROUP_OFFICE,#	Presentation software	Office
+'Spreadsheet': GROUP_OFFICE,#	A spreadsheet	Office
+'WordProcessor':GROUP_OFFICE, #	A word processor	Office
+'2DGraphics': GROUP_GRAPHICS,#	2D based graphical application	Graphics
+'VectorGraphics': GROUP_GRAPHICS,#	Vector based graphical application	Graphics;2DGraphics
+'RasterGraphics': GROUP_GRAPHICS, #	Raster based graphical application	Graphics;2DGraphics
+'3DGraphics': GROUP_GRAPHICS, #	3D based graphical application	Graphics
+'Scanning': GROUP_GRAPHICS,#	Tool to scan a file/text	Graphics
+'OCR': GROUP_GRAPHICS, #	Optical character recognition application	Graphics;Scanning
+'Photography': GROUP_GRAPHICS, #Camera tools, etc.	Graphics or Office
+'Publishing' : GROUP_GRAPHICS, #	Desktop Publishing applications and Color Management tools	Graphics or Office
+'Viewer': GROUP_OFFICE, #Tool to view e.g. a graphic or pdf file	Graphics or Office
+'TextTools': GROUP_ACCESSORIES, #A text tool utiliy	Utility
+'DesktopSettings': GROUP_SYSTEM,#	Configuration tool for the GUI	Settings
+'HardwareSettings': GROUP_SYSTEM, #	A tool to manage hardware components, like sound cards, video cards or printers	Settings
+'Printing': GROUP_SYSTEM, #	A tool to manage printers	HardwareSettings;Settings
+'PackageManager': GROUP_SYSTEM, #	A package manager application	Settings
+'Dialup': GROUP_INTERNET,#	A dial-up program	Network
+'InstantMessaging': GROUP_INTERNET, #	An instant messaging client	Network
+'Chat': GROUP_INTERNET,#	A chat client	Network
+'IRCClient': GROUP_INTERNET,#	An IRC client	Network
+'FileTransfer': GROUP_INTERNET, #	Tools like FTP or P2P programs	Network
+'HamRadio': GROUP_INTERNET, #	HAM radio software	Network or Audio
+'News': GROUP_INTERNET, #	A news reader or a news ticker	Network
+'P2P': GROUP_INTERNET, #	A P2P program	Network
+'RemoteAccess': GROUP_INTERNET, #	A tool to remotely manage your PC	Network
+'Telephony': GROUP_INTERNET,#	Telephony via PC	Network
+'TelephonyTools': GROUP_INTERNET, #	Telephony tools, to dial a number, manage PBX, ...	Utility
+'VideoConference': GROUP_INTERNET, #	Video Conference software	Network
+'WebBrowser': GROUP_INTERNET, #	A web browser	Network
+'WebDevelopment': GROUP_INTERNET, #	A tool for web developers	Network or Development
+'Midi': GROUP_MULTIMEDIA, #	An app related to MIDI	AudioVideo;Audio
+'Mixer': GROUP_MULTIMEDIA,#	Just a mixer	AudioVideo;Audio
+'Sequencer':GROUP_MULTIMEDIA,#	A sequencer	AuioVideo;Audio
+'Tuner': GROUP_MULTIMEDIA,#	A tuner	AudioVideo;Audio
+'TV': GROUP_MULTIMEDIA,#	A TV application	AudioVideo;Video
+'AudioVideoEditing': GROUP_MULTIMEDIA,#	Application to edit audio/video files	Audio or Video or AudioVideo
+'Player': GROUP_MULTIMEDIA,#	Application to play audio/video files	Audio or Video or AudioVideo
+'Recorder': GROUP_MULTIMEDIA,#	Application to record audio/video files	Audio or Video or AudioVideo
+'DiscBurning':GROUP_MULTIMEDIA,#	Application to burn a disc	AudioVideo
+'ActionGame':GROUP_GAMES,#	An action game	Game
+'AdventureGame':GROUP_GAMES,#	Adventure style game	Game
+'ArcadeGame':GROUP_GAMES,#	Arcade style game	Game
+'BoardGame':GROUP_GAMES,#	A board game	Game
+'BlocksGame':GROUP_GAMES,#	Falling blocks game	Game
+'CardGame':GROUP_GAMES,#	A card game	Game
+'KidsGame': GROUP_GAMES,#	A game for kids	Game
+'LogicGame':GROUP_GAMES,#	Logic games like puzzles, etc	Game
+'RolePlaying':GROUP_GAMES,#	A role playing game	Game
+'Simulation':GROUP_GAMES,#	A simulation game	Game
+'SportsGame': GROUP_GAMES, #A sports game	Game
+'StrategyGame': GROUP_GAMES,#	A strategy game	Game Art	Software to teach arts	Education
+'Construction':GROUP_GAMES,#	 	Education
+'Music': GROUP_MULTIMEDIA,#	Musical software	AudioVideo;Education
+'Languages':GROUP_EDUCATION,#	Software to learn foreign languages	Education
+'Science': GROUP_EDUCATION,#	Scientific software	Education
+'ArtificialIntelligence': GROUP_EDUCATION, #	Artificial Intelligence software	Education;Science
+'Astronomy': GROUP_EDUCATION,#	Astronomy software	Education;Science
+'Biology':GROUP_SYSTEM,#	Biology software	Education;Science
+'Chemistry':GROUP_EDUCATION,#	Chemistry software	Education;Science
+'ComputerScience':GROUP_EDUCATION,#	ComputerSience software	Education;Science
+'DataVisualization':GROUP_EDUCATION,#	Data visualization software	Education;Science
+'Economy':GROUP_EDUCATION,#	Economy software	Education
+'Electricity':GROUP_EDUCATION,#	Electricity software	Education;Science
+'Geography':GROUP_EDUCATION,#	Geography software	Education
+'Geology':GROUP_EDUCATION,#	Geology software	Education;Science
+'Geoscience':GROUP_EDUCATION,#	Geoscience software	Education;Science
+'History':GROUP_EDUCATION,#	History software	Education
+'ImageProcessing':GROUP_EDUCATION,#	Image Processing software	Education;Science
+'Literature':GROUP_EDUCATION,#	Literature software	Education
+'Math':GROUP_EDUCATION,#	Math software	Education;Science
+'NumericalAnalysis':GROUP_EDUCATION,#	Numerical analysis software	Education;Science;Math
+'MedicalSoftware':GROUP_EDUCATION,#	Medical software	Education;Science
+'Physics':GROUP_EDUCATION,#	Physics software	Education;Science
+'Robotics':GROUP_EDUCATION,#	Robotics software	Education;Science
+'Sports':GROUP_GRAPHICS,#	Sports software	Education
+'ParallelComputing':GROUP_EDUCATION,#	Parallel computing software	Education;Science;ComputerScience
+#'Amusement'	A simple amusement	 
+'Archiving': GROUP_ACCESSORIES,#	A tool to archive/backup data	Utility
+'Compression': GROUP_ACCESSORIES,#	A tool to manage compressed data/archives	Utility;Archiving
+#'Electronics'	Electronics software, e.g. a circuit designer	 
+'Emulator':GROUP_GAMES,#	Emulator of another platform, such as a DOS emulator	System or Game
+'Engineering':GROUP_EDUCATION,#	Engineering software, e.g. CAD programs	 
+'FileTools':GROUP_ACCESSORIES, #	A file tool utility	Utility or System
+'FileManager':GROUP_ACCESSORIES,#	A file manager	System;FileTools
+'TerminalEmulator':GROUP_ACCESSORIES,#	A terminal emulator application	System
+'Filesystem':GROUP_SYSTEM, #	A file system tool	System
+'Monitor':GROUP_SYSTEM,#	Monitor application/applet that monitors some resource or activity	System
+'Security':GROUP_SYSTEM,#	A security tool	Settings or System
+'Accessibility':GROUP_ACCESSIBILITY,#	Accessibility	Settings or Utility
+'Calculator':GROUP_ACCESSORIES,#	A calculator	Utility
+'Clock':GROUP_ACCESSORIES,#	A clock application/applet	Utility
+'TextEditor':GROUP_ACCESSORIES,#	A text editor	Utility
+'Documentation':GROUP_EDUCATION,#	Help or documentation	 
+'Core':GROUP_SYSTEM,#	Important application, core to the desktop such as a file manager or a help browser	 
+#KDE	Application based on KDE libraries	QT
+#GNOME	Application based on GNOME libraries	GTK
+#GTK	Application based on GTK+ libraries	 
+#Qt	Application based on Qt libraries	 
+#Motif	Application based on Motif libraries	 
+#Java	Application based on Java GUI libraries, such as AWT or Swing	 
+'ConsoleOnly':GROUP_ACCESSORIES,
 }
 
 groupMap = {}
commit 9abcc0c03f3815a41992ab009fede6b61bc780ea
Merge: ee0db30... dbc7387...
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Sun Feb 22 20:04:09 2009 -0600

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

commit ee0db30b2185fdbecf1f5dac285a4791d7bda0db
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Sun Feb 22 20:03:54 2009 -0600

    conary: fix the search ~installed filter

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index fa4f753..537fd61 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -180,8 +180,6 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         log.debug((searchlist, where))
 
         troveTupleList = cache.search(searchlist, where )
-        log.info("XMLCACHE results:")
-        log.info(troveTupleList)
 
         if len(troveTupleList) > 0 :
             for i in troveTupleList:
@@ -190,7 +188,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         else:
             log.info("NOT FOUND %s " % searchlist )
             pk = ConaryPk()
-            troveTupleList = pk.query( searchlist)
+            troveTupleList = pk.query(searchlist)
             log.info(troveTupleList)
             if not troveTupleList:
                 error = {}
@@ -259,10 +257,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             version = pkg["version"]
             trove = name, None , cli.flavor
             specList.append( trove  )
-        log.info(specList)
         trovesList = cli.repos.findTroves(cli.default_label, specList, allowMissing=True )
-        log.info(trovesList)
-
         pkgFilter = ConaryFilter(filters)
         troves = trovesList.values()
         for trovelst in troves:
diff --git a/backends/conary/conaryFilter.py b/backends/conary/conaryFilter.py
index 20bd4bf..59cbcfa 100644
--- a/backends/conary/conaryFilter.py
+++ b/backends/conary/conaryFilter.py
@@ -45,9 +45,10 @@ class ConaryFilter(PackagekitFilter):
         '''
         Return if the packages are installed
         '''
+        if type(pkg) == tuple:
+            pkg = pkg[0]
         conary_cli = ConaryPk()
         result = conary_cli.query(pkg)
-            
         if result:
             return True
         else:
diff --git a/backends/conary/conarypk.py b/backends/conary/conarypk.py
index 9ed2545..13a5be5 100644
--- a/backends/conary/conarypk.py
+++ b/backends/conary/conarypk.py
@@ -9,6 +9,7 @@ from conary.versions import Label
 from conary.errors import TroveNotFound
 from conary.conaryclient.update import NoNewTrovesError
 
+from pkConaryLog import log
 
 class ConaryPk:
     def __init__(self):
commit dbc73873e6719d5eb2bd08b9a87dd3fb3d0ed998
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sun Feb 22 19:47:54 2009 +0100

    Trivial: The application id in the localised table should not be unique

diff --git a/contrib/app-install/pk-app-install-create.c b/contrib/app-install/pk-app-install-create.c
index 9373454..cfb3b34 100644
--- a/contrib/app-install/pk-app-install-create.c
+++ b/contrib/app-install/pk-app-install-create.c
@@ -112,7 +112,7 @@ main (int argc, char *argv[])
 			goto out;
 		}
 		statement = "CREATE TABLE localised ("
-			    "application_id TEXT primary key,"
+			    "application_id TEXT,"
 			    "application_name TEXT,"
 			    "application_summary TEXT,"
 			    "locale TEXT);";
commit 1dec96a93002088ec34c15b3636a7a6f5008fc68
Merge: db0b740... a3630a8...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Sun Feb 22 16:47:47 2009 +0100

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

commit a3630a8b830494d50377d1a4a935ede06f69b191
Author: zhourongrong <zhourenren at gmail.com>
Date:   Sun Feb 22 05:06:02 2009 +0000

    updated
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/zh_CN.po b/po/zh_CN.po
index 56892d2..a2171b3 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -3,15 +3,15 @@
 # This file is distributed under the same license as the  package.
 # Chen Yu <jcomee at gmail.com>, 2008
 # 甘露(Gan Lu) <rhythm.gan at gmail.com>, 2008
-# 闫丰刚 (sainry)<sainry at gmail.com> 2008
+# zhou renren <zhourenren at gmail.com>,2009
 #
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-15 16:57+0000\n"
-"PO-Revision-Date: 2008-11-23 19:47+0800\n"
+"POT-Creation-Date: 2009-02-17 08:37+0000\n"
+"PO-Revision-Date: 2009-02-21 13:48+0700\n"
 "Last-Translator: 甘露(Gan Lu) <rhythm.gan at gmail.com>\n"
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
@@ -21,680 +21,760 @@ msgstr ""
 #. TRANSLATORS: this is an atomic transaction
 #: ../client/pk-console.c:230
 msgid "Transaction"
-msgstr ""
+msgstr "处理"
 
 #. TRANSLATORS: this is the time the transaction was started in system timezone
 #: ../client/pk-console.c:232
 msgid "System time"
-msgstr ""
+msgstr "系统时间"
 
 #. TRANSLATORS: this is if the transaction succeeded or not
 #: ../client/pk-console.c:234
 msgid "Succeeded"
-msgstr ""
+msgstr "成功"
 
 #. TRANSLATORS: if the repo is enabled
-#: ../client/pk-console.c:234 ../client/pk-console.c:377
+#: ../client/pk-console.c:234
+#: ../client/pk-console.c:401
 msgid "True"
-msgstr ""
+msgstr "是"
 
-#: ../client/pk-console.c:234 ../client/pk-console.c:377
+#: ../client/pk-console.c:234
+#: ../client/pk-console.c:401
 msgid "False"
-msgstr ""
+msgstr "否"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #: ../client/pk-console.c:236
 msgid "Role"
-msgstr ""
+msgstr "操作"
 
 #. TRANSLATORS: this is The duration of the transaction
 #: ../client/pk-console.c:241
 msgid "Duration"
-msgstr ""
+msgstr "持续时间"
 
 #: ../client/pk-console.c:241
 msgid "(seconds)"
-msgstr ""
+msgstr "秒"
 
 #. TRANSLATORS: this is The command line used to do the action
 #: ../client/pk-console.c:245
-#, fuzzy
 msgid "Command line"
-msgstr "命令失败"
+msgstr "命令行"
 
 #. TRANSLATORS: this is the user ID of the user that started the action
 #: ../client/pk-console.c:247
 msgid "User ID"
-msgstr ""
+msgstr "用户ID"
 
 #. TRANSLATORS: this is the username, e.g. hughsie
 #: ../client/pk-console.c:254
 msgid "Username"
-msgstr ""
+msgstr "用户名"
 
 #. TRANSLATORS: this is the users real name, e.g. "Richard Hughes"
 #: ../client/pk-console.c:258
 msgid "Real name"
-msgstr ""
+msgstr "真实姓名"
 
 #: ../client/pk-console.c:266
 msgid "Affected packages:"
-msgstr ""
+msgstr "受影响的软件包"
 
 #: ../client/pk-console.c:268
 msgid "Affected packages: None"
-msgstr ""
+msgstr "受影响的软件包:无"
 
 #. TRANSLATORS: this is the distro, e.g. Fedora 10
 #: ../client/pk-console.c:293
 msgid "Distribution"
-msgstr ""
+msgstr "发布"
 
 #. TRANSLATORS: this is type of update, stable or testing
 #: ../client/pk-console.c:295
 msgid "Type"
-msgstr ""
+msgstr "类型"
 
 #. TRANSLATORS: this is any summary text describing the upgrade
 #. TRANSLATORS: this is the summary of the group
-#: ../client/pk-console.c:297 ../client/pk-console.c:319
+#: ../client/pk-console.c:297
+#: ../client/pk-console.c:320
 msgid "Summary"
-msgstr ""
+msgstr "摘要"
 
 #. TRANSLATORS: this is the group category name
 #: ../client/pk-console.c:309
 msgid "Category"
-msgstr ""
+msgstr "分类"
 
 #. TRANSLATORS: this is group identifier
 #: ../client/pk-console.c:311
 msgid "ID"
-msgstr ""
+msgstr "ID"
 
 #. TRANSLATORS: this is the parent group
 #: ../client/pk-console.c:314
 msgid "Parent"
-msgstr ""
+msgstr "上一级"
 
-#: ../client/pk-console.c:316
+#. TRANSLATORS: this is the name of the parent group
+#: ../client/pk-console.c:317
 msgid "Name"
-msgstr ""
+msgstr "上一级组名"
 
 #. TRANSLATORS: this is preferred icon for the group
-#: ../client/pk-console.c:322
+#: ../client/pk-console.c:323
 msgid "Icon"
-msgstr ""
+msgstr "图标"
 
 #. TRANSLATORS: this is a header for the package that can be updated
-#: ../client/pk-console.c:337
+#: ../client/pk-console.c:338
 msgid "Details about the update:"
 msgstr "本次更新详情:"
 
-#: ../client/pk-console.c:338
-#, fuzzy
+#. TRANSLATORS: details about the update, package name and version
+#: ../client/pk-console.c:340
 msgid "Package"
-msgstr "软件包文件"
+msgstr "软件包"
 
-#: ../client/pk-console.c:340
+#. TRANSLATORS: details about the update, any packages that this update updates
+#: ../client/pk-console.c:343
 msgid "Updates"
-msgstr ""
+msgstr "æ›´æ–°"
 
-#: ../client/pk-console.c:342
+#. TRANSLATORS: details about the update, any packages that this update obsoletes
+#: ../client/pk-console.c:347
 msgid "Obsoletes"
-msgstr ""
+msgstr "过时"
 
-#: ../client/pk-console.c:344
+#. TRANSLATORS: details about the update, the vendor URLs
+#: ../client/pk-console.c:351
 msgid "Vendor"
-msgstr ""
+msgstr "厂商"
 
-#: ../client/pk-console.c:346
+#. TRANSLATORS: details about the update, the bugzilla URLs
+#: ../client/pk-console.c:355
 msgid "Bugzilla"
-msgstr ""
+msgstr "Bugzilla"
 
-#: ../client/pk-console.c:348
+#. TRANSLATORS: details about the update, the CVE URLs
+#: ../client/pk-console.c:359
 msgid "CVE"
-msgstr ""
+msgstr "CVE"
 
-#: ../client/pk-console.c:350
+#. TRANSLATORS: details about the update, if the package requires a restart
+#: ../client/pk-console.c:363
 msgid "Restart"
-msgstr ""
+msgstr "重启"
 
-#: ../client/pk-console.c:352
+#. TRANSLATORS: details about the update, any description of the update
+#: ../client/pk-console.c:367
 msgid "Update text"
-msgstr ""
+msgstr "更新文档"
 
-#: ../client/pk-console.c:354
+#. TRANSLATORS: details about the update, the changelog for the package
+#: ../client/pk-console.c:371
 msgid "Changes"
-msgstr ""
+msgstr "变化"
 
-#: ../client/pk-console.c:356
+#. TRANSLATORS: details about the update, the ongoing state of the update
+#: ../client/pk-console.c:375
 msgid "State"
-msgstr ""
+msgstr "状态"
 
-#: ../client/pk-console.c:359
+#. TRANSLATORS: details about the update, date the update was issued
+#: ../client/pk-console.c:380
 msgid "Issued"
-msgstr ""
+msgstr "发布"
 
-#: ../client/pk-console.c:362
+#. TRANSLATORS: details about the update, date the update was updated
+#: ../client/pk-console.c:385
 msgid "Updated"
-msgstr ""
+msgstr "已更新"
 
-#: ../client/pk-console.c:448 ../client/pk-console.c:450
+#: ../client/pk-console.c:472
+#: ../client/pk-console.c:474
 msgid "Percentage"
-msgstr ""
+msgstr "百分比"
 
-#: ../client/pk-console.c:450
+#: ../client/pk-console.c:474
 msgid "Unknown"
-msgstr ""
+msgstr "未知"
 
 #. TRANSLATORS: a package requires the system to be restarted
-#: ../client/pk-console.c:501
+#: ../client/pk-console.c:525
 msgid "System restart required by:"
-msgstr ""
+msgstr "要求系统重启的软件包:"
 
 #. TRANSLATORS: a package requires the session to be restarted
-#: ../client/pk-console.c:504
-#, fuzzy
+#: ../client/pk-console.c:528
 msgid "Session restart required:"
-msgstr "要求软件库签名"
+msgstr "要求会话重启的软件包:"
 
 #. TRANSLATORS: a package requires the application to be restarted
-#: ../client/pk-console.c:507
+#: ../client/pk-console.c:531
 msgid "Application restart required by:"
-msgstr ""
+msgstr "要求应用程序重启的软件包:"
 
-#: ../client/pk-console.c:543
+#. TRANSLATORS: a package needs to restart they system
+#: ../client/pk-console.c:568
 msgid "Please restart the computer to complete the update."
 msgstr "请重新启动计算机以完成本次更新。"
 
-#: ../client/pk-console.c:545
+#. TRANSLATORS: a package needs to restart the session
+#: ../client/pk-console.c:571
 msgid "Please logout and login to complete the update."
 msgstr "请登出并登录以完成本次更新。"
 
-#: ../client/pk-console.c:547
+#. TRANSLATORS: a package needs to restart the application
+#: ../client/pk-console.c:574
 msgid "Please restart the application as it is being used."
 msgstr "请重新启动正在使用中的程序。"
 
 #. TRANSLATORS: The package is already installed on the system
-#: ../client/pk-console.c:659
-#, fuzzy, c-format
+#: ../client/pk-console.c:687
+#, c-format
 msgid "The package %s is already installed"
 msgstr "该软件包 '%s' 已经安装"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:667
-#, fuzzy, c-format
+#: ../client/pk-console.c:695
+#, c-format
 msgid "The package %s could not be installed: %s"
 msgstr "该软件包 '%s' 无法安装:%s"
 
 #. TRANSLATORS: There was a programming error that shouldn't happen. The detailed error follows
-#: ../client/pk-console.c:692 ../client/pk-console.c:719
-#: ../client/pk-console.c:815 ../client/pk-console.c:932
-#: ../client/pk-tools-common.c:61 ../client/pk-tools-common.c:79
+#: ../client/pk-console.c:720
+#: ../client/pk-console.c:747
+#: ../client/pk-console.c:843
+#: ../client/pk-console.c:960
+#: ../client/pk-tools-common.c:61
+#: ../client/pk-tools-common.c:79
 #: ../client/pk-tools-common.c:86
 #, c-format
 msgid "Internal error: %s"
 msgstr "内部错误:%s"
 
 #. TRANSLATORS: There was an error installing the packages. The detailed error follows
-#: ../client/pk-console.c:700 ../client/pk-console.c:1327
+#: ../client/pk-console.c:728
+#: ../client/pk-console.c:1355
 #, c-format
 msgid "This tool could not install the packages: %s"
 msgstr "该工具无法安装本软件包:%s"
 
 #. TRANSLATORS: There was an error installing the files. The detailed error follows
-#: ../client/pk-console.c:727
+#: ../client/pk-console.c:755
 #, c-format
 msgid "This tool could not install the files: %s"
 msgstr "本工具无法安装文件:%s"
 
 #. TRANSLATORS: The package name was not found in the installed list. The detailed error follows
-#: ../client/pk-console.c:783
-#, fuzzy, c-format
+#: ../client/pk-console.c:811
+#, c-format
 msgid "This tool could not remove %s: %s"
-msgstr "该工具无法删除: '%s': %s"
+msgstr "该工具无法删除 %s:%s"
 
 #. TRANSLATORS: There was an error removing the packages. The detailed error follows
-#: ../client/pk-console.c:806 ../client/pk-console.c:844
-#: ../client/pk-console.c:877
+#: ../client/pk-console.c:834
+#: ../client/pk-console.c:872
+#: ../client/pk-console.c:905
 #, c-format
 msgid "This tool could not remove the packages: %s"
 msgstr "该工具无法删除本软件包:%s"
 
 #. TRANSLATORS: When removing, we might have to remove other dependencies
-#: ../client/pk-console.c:856
+#: ../client/pk-console.c:884
 msgid "The following packages have to be removed:"
 msgstr "下列软件包必须被删除:"
 
 #. TRANSLATORS: We are checking if it's okay to remove a list of packages
-#: ../client/pk-console.c:863
+#: ../client/pk-console.c:891
 msgid "Proceed removing additional packages?"
 msgstr "开始进行删除额外的软件包吗?"
 
 #. TRANSLATORS: We did not remove any packages
-#: ../client/pk-console.c:868
+#: ../client/pk-console.c:896
 msgid "The package removal was canceled!"
 msgstr "已取消删除本软件包!"
 
 #. TRANSLATORS: The package name was not found in any software sources
-#: ../client/pk-console.c:909
-#, fuzzy, c-format
+#: ../client/pk-console.c:937
+#, c-format
 msgid "This tool could not download the package %s as it could not be found"
 msgstr "本工具无法下载软件包 '%s' (无法找到)"
 
 #. TRANSLATORS: Could not download the packages for some reason. The detailed error follows
-#: ../client/pk-console.c:940
+#: ../client/pk-console.c:968
 #, c-format
 msgid "This tool could not download the packages: %s"
 msgstr "本工具无法下载该软件包:%s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:967 ../client/pk-console.c:976
-#, fuzzy, c-format
+#: ../client/pk-console.c:995
+#: ../client/pk-console.c:1004
+#, c-format
 msgid "This tool could not update %s: %s"
-msgstr "该工具无法更新 '%s': %s"
+msgstr "该工具无法更新 %s:%s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:998 ../client/pk-console.c:1006
-#, fuzzy, c-format
+#: ../client/pk-console.c:1026
+#: ../client/pk-console.c:1034
+#, c-format
 msgid "This tool could not get the requirements for %s: %s"
-msgstr "本工具无法得到 '%s': %s 的需求"
+msgstr "本工具无法得到 %s 的需求:%s "
 
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
-#: ../client/pk-console.c:1028 ../client/pk-console.c:1036
-#, fuzzy, c-format
+#: ../client/pk-console.c:1056
+#: ../client/pk-console.c:1064
+#, c-format
 msgid "This tool could not get the dependencies for %s: %s"
-msgstr "本工具无法得到 '%s' 的依赖关系: %s"
+msgstr "本工具无法得到 %s 的依赖关系:%s"
 
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
-#: ../client/pk-console.c:1058 ../client/pk-console.c:1066
-#, fuzzy, c-format
+#: ../client/pk-console.c:1086
+#: ../client/pk-console.c:1094
+#, c-format
 msgid "This tool could not get package details for %s: %s"
-msgstr "该工具无法得到 '%s' 的软件包详情:%s"
+msgstr "该工具无法得到 %s 的软件包详情:%s"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:1088
-#, fuzzy, c-format
+#: ../client/pk-console.c:1116
+#, c-format
 msgid "This tool could not find the files for %s: %s"
-msgstr "该工具无法找到 '%s' 的文件:%s"
+msgstr "该工具无法找到 %s 的文件:%s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:1096
-#, fuzzy, c-format
+#: ../client/pk-console.c:1124
+#, c-format
 msgid "This tool could not get the file list for %s: %s"
-msgstr "该工具无法得到 '%s' 的文件清单:%s"
+msgstr "该工具无法得到 %s 的文件清单:%s"
 
 #. TRANSLATORS: There was an error getting the list of packages. The filename follows
-#: ../client/pk-console.c:1118
+#: ../client/pk-console.c:1146
 #, c-format
 msgid "File already exists: %s"
 msgstr "文件已存在: %s"
 
 #. TRANSLATORS: follows a list of packages to install
-#: ../client/pk-console.c:1123 ../client/pk-console.c:1179
-#: ../client/pk-console.c:1254
+#: ../client/pk-console.c:1151
+#: ../client/pk-console.c:1207
+#: ../client/pk-console.c:1282
 msgid "Getting package list"
 msgstr "正在获得软件包列表..."
 
 #. TRANSLATORS: There was an error getting the list of packages. The detailed error follows
-#: ../client/pk-console.c:1129 ../client/pk-console.c:1185
-#: ../client/pk-console.c:1260
+#: ../client/pk-console.c:1157
+#: ../client/pk-console.c:1213
+#: ../client/pk-console.c:1288
 #, c-format
 msgid "This tool could not get package list: %s"
 msgstr "该工具无法得到软件表列表:%s"
 
 #. TRANSLATORS: There was an error saving the list
-#: ../client/pk-console.c:1140
-#, c-format
+#: ../client/pk-console.c:1168
 msgid "Failed to save to disk"
 msgstr "存盘失败"
 
 #. TRANSLATORS: There was an error getting the list. The filename follows
-#: ../client/pk-console.c:1174 ../client/pk-console.c:1249
+#: ../client/pk-console.c:1202
+#: ../client/pk-console.c:1277
 #, c-format
 msgid "File does not exist: %s"
 msgstr "文件不存在 : %s"
 
 #. TRANSLATORS: header to a list of packages newly added
-#: ../client/pk-console.c:1206
+#: ../client/pk-console.c:1234
 msgid "Packages to add"
 msgstr "添加软件包"
 
 #. TRANSLATORS: header to a list of packages removed
-#: ../client/pk-console.c:1214
+#: ../client/pk-console.c:1242
 msgid "Packages to remove"
 msgstr "删除软件包"
 
 #. TRANSLATORS: We didn't find any differences
-#: ../client/pk-console.c:1282
-#, c-format
+#: ../client/pk-console.c:1310
 msgid "No new packages need to be installed"
 msgstr "没有新的软件包安装"
 
 #. TRANSLATORS: follows a list of packages to install
-#: ../client/pk-console.c:1288
+#: ../client/pk-console.c:1316
 msgid "To install"
 msgstr "安装"
 
 #. TRANSLATORS: searching takes some time....
-#: ../client/pk-console.c:1299
+#: ../client/pk-console.c:1327
 msgid "Searching for package: "
 msgstr "搜索软件包: "
 
 #. TRANSLATORS: package was not found -- this is the end of a string ended in ...
-#: ../client/pk-console.c:1303
+#: ../client/pk-console.c:1331
 msgid "not found."
 msgstr "没有找到"
 
 #. TRANSLATORS: We didn't find any packages to install
-#: ../client/pk-console.c:1314
-#, c-format
+#: ../client/pk-console.c:1342
 msgid "No packages can be found to install"
 msgstr "找不到软件包安装"
 
 #. TRANSLATORS: installing new packages from package list
-#: ../client/pk-console.c:1320
+#: ../client/pk-console.c:1348
 msgid "Installing packages"
 msgstr "正在安装软件包..."
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:1356
-#, fuzzy, c-format
+#: ../client/pk-console.c:1384
+#, c-format
 msgid "This tool could not find the update details for %s: %s"
-msgstr "该工具无法找到 '%s' 的更新详情:%s"
+msgstr "该工具无法找到 %s 的更新详情:%s"
 
 #. TRANSLATORS: There was an error getting the details about the update for the package. The detailed error follows
-#: ../client/pk-console.c:1364
-#, fuzzy, c-format
+#: ../client/pk-console.c:1392
+#, c-format
 msgid "This tool could not get the update details for %s: %s"
-msgstr "该工具无法为 '%s': %s 得到更新详情"
+msgstr "该工具无法得到 %s 的更新详情:%s"
 
 #. TRANSLATORS: This was an unhandled error, and we don't have _any_ context
-#: ../client/pk-console.c:1410
+#: ../client/pk-console.c:1438
 msgid "Error:"
 msgstr "错误:"
 
 #. TRANSLATORS: This a list of details about the package
-#: ../client/pk-console.c:1424
+#: ../client/pk-console.c:1452
 msgid "Package description"
 msgstr "软件包描述"
 
 #. TRANSLATORS: This a list files contained in the package
-#: ../client/pk-console.c:1458
+#: ../client/pk-console.c:1486
 msgid "Package files"
 msgstr "软件包文件"
 
 #. TRANSLATORS: This where the package has no files
-#: ../client/pk-console.c:1466
+#: ../client/pk-console.c:1494
 msgid "No files"
 msgstr "没有文件"
 
 #. TRANSLATORS: This a request for a GPG key signature from the backend, which the client will prompt for later
-#: ../client/pk-console.c:1489
+#: ../client/pk-console.c:1517
 msgid "Repository signature required"
 msgstr "要求软件库签名"
 
 #. TRANSLATORS: This a prompt asking the user to import the security key
-#: ../client/pk-console.c:1499
+#: ../client/pk-console.c:1527
 msgid "Do you accept this signature?"
 msgstr "你接受该签名吗?"
 
 #. TRANSLATORS: This is where the user declined the security key
-#: ../client/pk-console.c:1503
+#: ../client/pk-console.c:1531
 msgid "The signature was not accepted."
 msgstr "没有接受签名。"
 
 #. TRANSLATORS: This a request for a EULA
-#: ../client/pk-console.c:1537
+#: ../client/pk-console.c:1565
 msgid "End user license agreement required"
 msgstr "需要最终用户许可协议"
 
 #. TRANSLATORS: This a prompt asking the user to agree to the license
-#: ../client/pk-console.c:1544
+#: ../client/pk-console.c:1572
 msgid "Do you agree to this license?"
 msgstr "你同意本许可吗?"
 
 #. TRANSLATORS: This is where the user declined the license
-#: ../client/pk-console.c:1548
+#: ../client/pk-console.c:1576
 msgid "The license was refused."
 msgstr "拒绝该许可。"
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1577
+#: ../client/pk-console.c:1605
 msgid "The daemon crashed mid-transaction!"
 msgstr "后台程序在事务处理中期崩溃!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1630
+#: ../client/pk-console.c:1658
 msgid "PackageKit Console Interface"
 msgstr "PackageKit 终端界面"
 
-#: ../client/pk-console.c:1630
+#. these are commands we can use with pkcon
+#: ../client/pk-console.c:1660
 msgid "Subcommands:"
 msgstr "子命令:"
 
-#: ../client/pk-console.c:1719 ../client/pk-generate-pack.c:184
+#. TRANSLATORS: command line argument, if we should show debugging information
+#. TRANSLATORS: if we should show debugging data
+#: ../client/pk-console.c:1750
+#: ../client/pk-generate-pack.c:185
 #: ../client/pk-monitor.c:115
 #: ../contrib/command-not-found/pk-command-not-found.c:510
-#: ../src/pk-main.c:192
+#: ../src/pk-main.c:199
 msgid "Show extra debugging information"
 msgstr "显示额外的调试信息"
 
-#: ../client/pk-console.c:1721 ../client/pk-monitor.c:117
+#. TRANSLATORS: command line argument, just show the version string
+#: ../client/pk-console.c:1753
+#: ../client/pk-monitor.c:117
 msgid "Show the program version and exit"
 msgstr "显示本程序版本并退出"
 
-#: ../client/pk-console.c:1723
+#. TRANSLATORS: command line argument, use a filter to narrow down results
+#: ../client/pk-console.c:1756
 msgid "Set the filter, e.g. installed"
 msgstr "设置过滤器,例如已安装的"
 
-#: ../client/pk-console.c:1725
+#. TRANSLATORS: command line argument, work asynchronously
+#: ../client/pk-console.c:1759
 msgid "Exit without waiting for actions to complete"
 msgstr "不等操作完成即退出"
 
 #. TRANSLATORS: This is when we could not connect to the system bus, and is fatal
-#: ../client/pk-console.c:1752
+#: ../client/pk-console.c:1786
 msgid "This tool could not connect to system DBUS."
 msgstr "该工具无法连接到系统 DBUS。"
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1839
+#: ../client/pk-console.c:1873
 msgid "The filter specified was invalid"
 msgstr "过滤器指定非法"
 
-#: ../client/pk-console.c:1856
-msgid "You need to specify a search type, e.g. name"
-msgstr "你需要指定某个搜索类型,例如名字"
-
-#: ../client/pk-console.c:1861 ../client/pk-console.c:1868
-#: ../client/pk-console.c:1875 ../client/pk-console.c:1882
-#: ../client/pk-console.c:1990 ../client/pk-console.c:2000
-#: ../client/pk-console.c:2007 ../client/pk-console.c:2014
-msgid "You need to specify a search term"
-msgstr "你需要指定某个搜索术语"
-
-#: ../client/pk-console.c:1887
+#. TRANSLATORS: a search type can be name, details, file, etc
+#: ../client/pk-console.c:1891
+msgid "A search type is required, e.g. name"
+msgstr "你需要指定搜索类型,如软件包名"
+
+#. TRANSLATORS: the user needs to provide a search term
+#: ../client/pk-console.c:1897
+#: ../client/pk-console.c:1905
+#: ../client/pk-console.c:1913
+#: ../client/pk-console.c:1921
+msgid "A search term is required"
+msgstr "你需要指定搜索条件"
+
+#. TRANSLATORS: the search type was provided, but invalid
+#: ../client/pk-console.c:1927
 msgid "Invalid search type"
 msgstr "无效的搜索类型"
 
-#: ../client/pk-console.c:1892
-msgid "You need to specify a package or file to install"
-msgstr "你需要指定某个软件包或文件来安装"
+#. TRANSLATORS: the user did not specify what they wanted to install
+#: ../client/pk-console.c:1933
+msgid "A package name or filename to install is required"
+msgstr "你需要为安装指定一个软件包名或文件名"
 
-#: ../client/pk-console.c:1899
-msgid "You need to specify a type, key_id and package_id"
-msgstr "你需要指定某个类型,证书ID或者软件包ID"
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1941
+msgid "A type, key_id and package_id are required"
+msgstr "需要指定某个类型,证书ID或者软件包ID"
 
-#: ../client/pk-console.c:1906
-msgid "You need to specify a package to remove"
-msgstr "你需要指定某个软件包来删除"
+#. TRANSLATORS: the user did not specify what they wanted to remove
+#: ../client/pk-console.c:1949
+msgid "A package name to remove is required"
+msgstr "你需要为卸载指定一个软件包名"
 
-#: ../client/pk-console.c:1912
-msgid ""
-"You need to specify the destination directory and then the packages to "
-"download"
-msgstr "你需要指定目的地目录以及软件包来下载"
+#. TRANSLATORS: the user did not specify anything about what to download or where
+#: ../client/pk-console.c:1956
+msgid "A destination directory and then the package names to download are required"
+msgstr "需要指定目的地目录以及软件包名来下载"
 
-#: ../client/pk-console.c:1917
+#. TRANSLATORS: the directory does not exist, so we can't continue
+#: ../client/pk-console.c:1962
 msgid "Directory not found"
 msgstr "目录没有找到"
 
-#: ../client/pk-console.c:1923
-msgid "You need to specify a licence identifier (eula-id)"
-msgstr "你需要指定某个许可鉴别 (eula-id)"
-
-#: ../client/pk-console.c:1939
-msgid "You need to specify a package name to resolve"
-msgstr "你需要指定某个软件包名字来解决依赖关系"
-
-#: ../client/pk-console.c:1946 ../client/pk-console.c:1953
-msgid "You need to specify a repository name"
-msgstr "你需要指定某个软件库名字"
-
-#: ../client/pk-console.c:1960
-msgid "You need to specify a repo name/parameter and value"
-msgstr "你需要指定某个软件库名字/参数或值"
-
-#: ../client/pk-console.c:1972
-msgid "You need to specify an action, e.g. 'update-system'"
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1969
+msgid "A licence identifier (eula-id) is required"
+msgstr "需要指定某个许可证鉴别 (eula-id)"
+
+#. TRANSLATORS: The user did not specify a package name
+#: ../client/pk-console.c:1986
+msgid "A package name to resolve is required"
+msgstr "你需要为解析指定一个软件包名"
+
+#. TRANSLATORS: The user did not specify a repository (software source) name
+#: ../client/pk-console.c:1994
+#: ../client/pk-console.c:2002
+msgid "A repository name is required"
+msgstr "要求软件库名"
+
+#. TRANSLATORS: The user didn't provide any data
+#: ../client/pk-console.c:2010
+msgid "A repo name, parameter and value are required"
+msgstr "你需要指定某个软件库名字,参数或值"
+
+#. TRANSLATORS: The user didn't specify what action to use
+#: ../client/pk-console.c:2023
+msgid "An action, e.g. 'update-system' is required"
 msgstr "你需要指定某个行动,例如“更新系统”"
 
-#: ../client/pk-console.c:1977
-msgid "You need to specify a correct role"
-msgstr "你需要指定某个正确的角色"
-
-#: ../client/pk-console.c:1982
-msgid "Failed to get last time"
-msgstr "无法得到最后一次时间"
-
-#: ../client/pk-console.c:2021
-msgid "You need to specify a package to find the details for"
-msgstr "你需要指定某个软件包已找到相关详情"
-
-#: ../client/pk-console.c:2028
-msgid "You need to specify a package to find the files for"
-msgstr "你需要指定某个软件包已找到相关文件"
+#. TRANSLATORS: The user specified an invalid action
+#: ../client/pk-console.c:2029
+msgid "A correct role is required"
+msgstr "需要一个正确响应"
 
+#. TRANSLATORS: we keep a database updated with the time that an action was last executed
 #: ../client/pk-console.c:2035
-msgid "You need to specify a list file to create"
-msgstr "你需要指定一个要创建的文件序列"
-
-#: ../client/pk-console.c:2043 ../client/pk-console.c:2051
-msgid "You need to specify a list file to open"
-msgstr "你需要指定一个文件序列来打开"
+msgid "Failed to get the time since this action was last completed"
+msgstr "未获得最后一次操作的时间"
+
+#. TRANSLATORS: The user did not provide a package name
+#. TRANSLATORS: This is when the user fails to supply the package name
+#: ../client/pk-console.c:2044
+#: ../client/pk-console.c:2055
+#: ../client/pk-console.c:2063
+#: ../client/pk-console.c:2079
+#: ../client/pk-console.c:2087
+#: ../client/pk-generate-pack.c:241
+msgid "A package name is required"
+msgstr "需要软件包名"
+
+#. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
+#: ../client/pk-console.c:2071
+msgid "A package provide string is required"
+msgstr "你需要指定特定参数"
+
+#. TRANSLATORS: The user didn't specify a filename to create as a list
+#: ../client/pk-console.c:2095
+msgid "A list file name to create is required"
+msgstr "需要建立一个文件列表"
+
+#. TRANSLATORS: The user didn't specify a filename to open as a list
+#: ../client/pk-console.c:2104
+#: ../client/pk-console.c:2113
+msgid "A list file to open is required"
+msgstr "需要打开一个文件列表"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:2104
+#: ../client/pk-console.c:2166
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "不支持 '%s' 选项"
 
 #. TRANSLATORS: User does not have permission to do this
-#: ../client/pk-console.c:2117
-msgid "You don't have the necessary privileges for this operation"
+#: ../client/pk-console.c:2179
+msgid "Incorrect privileges for this operation"
 msgstr "你没有本次操作需要的必要权限"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:2120
+#: ../client/pk-console.c:2182
 msgid "Command failed"
 msgstr "命令失败"
 
 #. TRANSLATORS: This is the state of the transaction
-#: ../client/pk-generate-pack.c:100
+#: ../client/pk-generate-pack.c:101
 msgid "Downloading"
 msgstr "正在下载"
 
 #. TRANSLATORS: This is when the main packages are being downloaded
-#: ../client/pk-generate-pack.c:120
+#: ../client/pk-generate-pack.c:121
 msgid "Downloading packages"
 msgstr "正在下载软件包"
 
 #. TRANSLATORS: This is when the dependency packages are being downloaded
-#: ../client/pk-generate-pack.c:125
+#: ../client/pk-generate-pack.c:126
 msgid "Downloading dependencies"
 msgstr "正在下载依赖关系"
 
-#: ../client/pk-generate-pack.c:186
+#. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
+#: ../client/pk-generate-pack.c:188
 msgid "Set the file name of dependencies to be excluded"
 msgstr "设置将被除外的依赖关系的文件名"
 
-#: ../client/pk-generate-pack.c:188
-msgid "The output directory (the current directory is used if ommitted)"
-msgstr "输出目录(使用当前目录如忘记指定)"
+#. TRANSLATORS: the output location
+#: ../client/pk-generate-pack.c:191
+msgid "The output file or directory (the current directory is used if ommitted)"
+msgstr "输出文件或目录(使用当前目录如忘记指定)"
 
-#: ../client/pk-generate-pack.c:190
+#. TRANSLATORS: put a list of packages in the pack
+#: ../client/pk-generate-pack.c:194
 msgid "The package to be put into the service pack"
 msgstr "将放入服务包的软件包"
 
-#: ../client/pk-generate-pack.c:192
+#. TRANSLATORS: put all pending updates in the pack
+#: ../client/pk-generate-pack.c:197
 msgid "Put all updates available in the service pack"
 msgstr "将所有可获得的更新放入服务包"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:220
+#: ../client/pk-generate-pack.c:225
 msgid "Neither --package or --updates option selected."
 msgstr "要么是选定了 --package 选项,要么是选定了 --updates 选项"
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:228
+#: ../client/pk-generate-pack.c:233
 msgid "Both options selected."
 msgstr "选定了两个选项"
 
+#. TRANSLATORS: This is when the user fails to supply the output
+#: ../client/pk-generate-pack.c:249
+msgid "A output directory or file name is required"
+msgstr "你需要指定输出的目录名或文件名"
+
+#. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
+#. TRANSLATORS: This is when the backend doesn't have the capability to download
+#: ../client/pk-generate-pack.c:267
+#: ../client/pk-generate-pack.c:273
+msgid "The package manager cannot perform this type of operation."
+msgstr "软件包管理器不能处理当前类型的操作"
+
+#. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
+#: ../client/pk-generate-pack.c:285
+msgid "If specifying a file, the service pack name must end with"
+msgstr "如果指定一个文件,文件后缀名必须是"
+
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:261
+#: ../client/pk-generate-pack.c:301
 msgid "A pack with the same name already exists, do you want to overwrite it?"
 msgstr "已经有同名软件包存在,你想要覆盖它吗?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:264
+#: ../client/pk-generate-pack.c:304
 msgid "The pack was not overwritten."
 msgstr "该软件包没有被覆盖"
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:276
+#: ../client/pk-generate-pack.c:317
 msgid "Failed to create directory:"
 msgstr "无法创建目录"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:285
+#: ../client/pk-generate-pack.c:327
 msgid "Failed to open package list."
 msgstr "无法打开软件包清单"
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:295
+#: ../client/pk-generate-pack.c:338
 msgid "Finding package name."
 msgstr "正在寻找软件包名"
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:299
+#: ../client/pk-generate-pack.c:342
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "无法找到软件包 '%s': %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:315
+#: ../client/pk-generate-pack.c:359
 msgid "Creating service pack..."
 msgstr "正在创建服务包..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:322
+#: ../client/pk-generate-pack.c:366
 #, c-format
 msgid "Service pack created '%s'"
 msgstr "服务包已创建 '%s'"
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:326
+#: ../client/pk-generate-pack.c:371
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "无法创建 '%s': %s"
 
-#: ../client/pk-monitor.c:132
+#. TRANSLATORS: this is a program that monitors PackageKit
+#: ../client/pk-monitor.c:133
 msgid "PackageKit Monitor"
 msgstr "PackageKit 监视器"
 
 #. TRANSLATORS: The package was not found in any software sources
 #: ../client/pk-tools-common.c:114
-#, c-format
 msgid "The package could not be found"
 msgstr "无法找到该软件包"
 
@@ -715,79 +795,72 @@ msgstr "请输入从1到 %i 的数字:"
 
 #. TRANSLATORS: we failed to find the package, this shouldn't happen
 #: ../contrib/command-not-found/pk-command-not-found.c:361
-#, fuzzy
 msgid "Failed to search for file"
-msgstr "存盘失败"
+msgstr "未找到该软件包"
 
 #. TRANSLATORS: we failed to launch the executable, the error follows
 #: ../contrib/command-not-found/pk-command-not-found.c:485
-#, fuzzy
 msgid "Failed to launch:"
-msgstr "无法得到最后一次时间"
+msgstr "无法执行"
 
 #. TRANSLATORS: tool that gets called when the command is not found
 #: ../contrib/command-not-found/pk-command-not-found.c:526
-#, fuzzy
 msgid "PackageKit Command Not Found"
-msgstr "PackageKit 监视器"
+msgstr "PackageKit 命令没有找到"
 
 #. TRANSLATORS: the prefix of all the output telling the user why it's not executing
 #: ../contrib/command-not-found/pk-command-not-found.c:548
-#, fuzzy
 msgid "Command not found."
-msgstr "没有找到"
+msgstr "命令未找到"
 
 #. TRANSLATORS: tell the user what we think the command is
 #: ../contrib/command-not-found/pk-command-not-found.c:555
-#, fuzzy
 msgid "Similar command is:"
-msgstr "子命令:"
+msgstr "可能命令是:"
 
 #. TRANSLATORS: Ask the user if we should run the similar command
 #: ../contrib/command-not-found/pk-command-not-found.c:564
 msgid "Run similar command:"
-msgstr ""
+msgstr "执行可能的命令:"
 
 #. TRANSLATORS: show the user a list of commands that they could have meant
 #. TRANSLATORS: show the user a list of commands we could run
 #: ../contrib/command-not-found/pk-command-not-found.c:576
 #: ../contrib/command-not-found/pk-command-not-found.c:585
-#, fuzzy
 msgid "Similar commands are:"
-msgstr "子命令:"
+msgstr "可能命令是:"
 
 #. TRANSLATORS: ask the user to choose a file to run
 #: ../contrib/command-not-found/pk-command-not-found.c:592
 msgid "Please choose a command to run"
-msgstr ""
+msgstr "请选择一条命令执行"
 
 #. TRANSLATORS: tell the user what package provides the command
 #: ../contrib/command-not-found/pk-command-not-found.c:607
 msgid "The package providing this file is:"
-msgstr ""
+msgstr "提供该命令的软件包是:"
 
 #. TRANSLATORS: as the user if we want to install a package to provide the command
 #: ../contrib/command-not-found/pk-command-not-found.c:612
 #, c-format
 msgid "Install package '%s' to provide command '%s'?"
-msgstr ""
+msgstr "安装包'%s' 提供命令 '%s'"
 
 #. TRANSLATORS: Show the user a list of packages that provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:633
 msgid "Packages providing this file are:"
-msgstr ""
+msgstr "提供该命令的软件包有:"
 
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:642
 msgid "Suitable packages are:"
-msgstr ""
+msgstr "适合的软件包是:"
 
 #. get selection
 #. TRANSLATORS: ask the user to choose a file to install
 #: ../contrib/command-not-found/pk-command-not-found.c:650
-#, fuzzy
 msgid "Please choose a package to install"
-msgstr "请选择正确的软件包:"
+msgstr "请选择要安装的某个软件包"
 
 #. TRANSLATORS: when we are getting data from the daemon
 #: ../contrib/browser-plugin/src/contents.cpp:298
@@ -811,6 +884,7 @@ msgstr "已安装版本"
 msgid "Run version %s now"
 msgstr "现在运行版本 %s"
 
+#. TRANSLATORS: run the application now
 #: ../contrib/browser-plugin/src/contents.cpp:324
 msgid "Run now"
 msgstr "现在运行"
@@ -854,166 +928,108 @@ msgstr "PackageKit 软件包清单"
 msgid "PackageKit Service Pack"
 msgstr "PackageKit 服务包"
 
-#: ../policy/org.freedesktop.packagekit.policy.in.h:1
-msgid "Accept EULA"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:2
-msgid "Authentication is required to accept a EULA"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:3
-msgid ""
-"Authentication is required to cancel a task that was not started by yourself"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:4
-msgid "Authentication is required to change software source parameters"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:5
-msgid ""
-"Authentication is required to consider a key used for signing packages as "
-"trusted"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:6
-msgid "Authentication is required to install a signed package"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:7
-msgid "Authentication is required to install an untrusted package"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:8
-msgid "Authentication is required to refresh the system sources"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:9
-msgid "Authentication is required to remove packages"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:10
-msgid "Authentication is required to rollback a transaction"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:11
-msgid ""
-"Authentication is required to set the network proxy used for downloading "
-"packages"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:12
-msgid "Authentication is required to update packages"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:13
-msgid "Cancel foreign task"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:14
-msgid "Change software source parameters"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:15
-#, fuzzy
-msgid "Install signed package"
-msgstr "正在安装软件包..."
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:16
-msgid "Install untrusted local file"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:17
-msgid "Refresh system sources"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:18
-msgid "Remove package"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:19
-msgid "Rollback to a previous transaction"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:20
-msgid "Set network proxy"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:21
-msgid "Trust a key used for signing packages"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:22
-msgid "Update packages"
-msgstr ""
-
-#: ../src/pk-main.c:86
+#. TRANSLATORS: failed due to DBus security
+#: ../src/pk-main.c:87
 msgid "Startup failed due to security policies on this machine."
 msgstr "由于本机的安全策略导致启动失败"
 
-#: ../src/pk-main.c:87
+#. TRANSLATORS: only two ways this can fail...
+#: ../src/pk-main.c:89
 msgid "This can happen for two reasons:"
 msgstr "发生这个可能有两个原因:"
 
-#: ../src/pk-main.c:88
+#. TRANSLATORS: only allowed to be owned by root
+#: ../src/pk-main.c:91
 msgid "The correct user is not launching the executable (usually root)"
 msgstr "用户正确但无法启动可执行程序(通常作为根用户)"
 
-#: ../src/pk-main.c:89
-msgid ""
-"The org.freedesktop.PackageKit.conf file is not installed in the system "
-"directory:"
+#. TRANSLATORS: or we are installed in a prefix
+#: ../src/pk-main.c:93
+msgid "The org.freedesktop.PackageKit.conf file is not installed in the system directory:"
 msgstr "org.freedesktop.PackageKit.conf 没有安装到系统目录中:"
 
-#: ../src/pk-main.c:188
+#. TRANSLATORS: a backend is the system package tool, e.g. yum, apt
+#: ../src/pk-main.c:193
 msgid "Packaging backend to use, e.g. dummy"
 msgstr "使用的打包后端,例如“伪”后端"
 
-#: ../src/pk-main.c:190
+#. TRANSLATORS: if we should run in the background
+#: ../src/pk-main.c:196
 msgid "Daemonize and detach from the terminal"
 msgstr "后台化并从终端中分离"
 
-#: ../src/pk-main.c:194
+#. TRANSLATORS: if we should not monitor how long we are inactive for
+#: ../src/pk-main.c:202
 msgid "Disable the idle timer"
-msgstr "禁止空间计时器"
+msgstr "禁止计时器"
 
-#: ../src/pk-main.c:196
+#. TRANSLATORS: show version
+#: ../src/pk-main.c:205
 msgid "Show version and exit"
 msgstr "显示版本并退出"
 
-#: ../src/pk-main.c:198
+#. TRANSLATORS: exit after we've started up, used for user profiling
+#: ../src/pk-main.c:208
 msgid "Exit after a small delay"
 msgstr "稍稍延迟后退出"
 
-#: ../src/pk-main.c:200
+#. TRANSLATORS: exit straight away, used for automatic profiling
+#: ../src/pk-main.c:211
 msgid "Exit after the engine has loaded"
 msgstr "引擎载入后退出"
 
-#: ../src/pk-main.c:214
+#. TRANSLATORS: describing the service that is running
+#: ../src/pk-main.c:226
 msgid "PackageKit service"
 msgstr "PackageKit 服务"
 
-#: ../src/pk-main.c:250
+#. TRANSLATORS: fatal error, dbus is not running
+#: ../src/pk-main.c:263
 msgid "Cannot connect to the system bus"
 msgstr "无法连接到系统总线"
 
-#: ../src/pk-main.c:299
+#. TRANSLATORS: cannot register on system bus, unknown reason
+#: ../src/pk-main.c:313
 #, c-format
 msgid "Error trying to start: %s\n"
-msgstr "出现错误当尝试启动 %s\n"
+msgstr "尝试启动时出错: %s\n"
+
+#~ msgid "You need to specify a search type, e.g. name"
+#~ msgstr "你需要指定某个搜索类型,例如名字"
+#~ msgid "You need to specify a search term"
+#~ msgstr "你需要指定某个搜索术语"
+#~ msgid "You need to specify a package or file to install"
+#~ msgstr "你需要指定某个软件包或文件来安装"
+#~ msgid "You need to specify a package to remove"
+#~ msgstr "你需要指定某个软件包来删除"
+#~ msgid "You need to specify a package name to resolve"
+#~ msgstr "你需要指定某个软件包名字来解决依赖关系"
+#~ msgid "You need to specify a repository name"
+#~ msgstr "你需要指定某个软件库名字"
+#~ msgid "You need to specify a correct role"
+#~ msgstr "你需要指定某个正确的角色"
+#~ msgid "Failed to get last time"
+#~ msgstr "无法得到最后一次时间"
+#~ msgid "You need to specify a package to find the details for"
+#~ msgstr "你需要指定某个软件包已找到相关详情"
+#~ msgid "You need to specify a package to find the files for"
+#~ msgstr "你需要指定某个软件包已找到相关文件"
+#~ msgid "You need to specify a list file to create"
+#~ msgstr "你需要指定一个要创建的文件序列"
+#~ msgid "You need to specify a list file to open"
+#~ msgstr "你需要指定一个文件序列来打开"
 
+#, fuzzy
+#~ msgid "Install signed package"
+#~ msgstr "正在安装软件包..."
 #~ msgid "This tool could not remove the packages: '%s'"
 #~ msgstr "该工具无法删除本软件包: '%s'"
-
 #~ msgid "Okay to import key?"
 #~ msgstr "可以导入证书吗?"
-
 #~ msgid "Did not import key"
 #~ msgstr "不导入证书"
-
 #~ msgid "Eula required"
 #~ msgstr "要求最终用户协议"
-
 #~ msgid "Do you agree?"
 #~ msgstr "你同意吗?"
+
commit 7007dc9243375fbca11cd49bb7fbe6da237be5bb
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Sat Feb 21 21:18:45 2009 -0600

    remove warning

diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index a2df848..f241592 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -65,7 +65,11 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
     #5  >> request> download
     def setChangesetHunk(self, num, total):
         log.info("callback. .......... set Changeset HUnk %s/%s" % (num, total ) )
-        self.progress.set_subpercent( num*100/float(total) )
+        if total > 0:
+            p = num*100/float(total)
+        else:
+            p = 0
+        self.progress.set_subpercent(p)
         self.disablepercent = True
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
commit 24e86b2ef8542beddca31df012532bba992c9a7f
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Sat Feb 21 11:28:33 2009 -0600

    conary: updatesystem do a stepdown percent

diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index e7c86e4..a2df848 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -36,7 +36,7 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([ 50,100 ]  )
+        self.progress.set_steps([ 50 ]  )
         self.disablepercent = False
         self.dostep = True
     #1
commit c37766c79801376a6e09f3948e5964a1a95d0506
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Sat Feb 21 02:48:36 2009 -0600

    conary: add a exception for run get-updates first
        and then update

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 81a17aa..fa4f753 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -229,8 +229,10 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         else:
             updJob = self._get_update(applyList, cache=False)
         self.allow_cancel(False)
-
-        restartDir = self.client.applyUpdateJob(updJob)
+        try:
+            restartDir = self.client.applyUpdateJob(updJob)
+        except errors.InternalConaryError:
+            self.error(ERROR_NO_PACKAGES_TO_UPDATE,"get-updates first and then update sytem")
         return updJob
 
     def _get_package_update(self, name, version, flavor):
@@ -455,7 +457,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         applyList = [ (x[0], (None, None), x[1:], True) for x in updateItems ]
 
         log.info(">>>>>>>>>> get update >>>>>>>>>>>>")
-        self._get_update(applyList)
+        #self._get_update(applyList)
         log.info(">>>>>>>>>> DO Update >>>>>>>>>>>>")
         self._do_update(applyList)
         log.info(">>>>>>>>>>END DO Update >>>>>>>>>>>>")
diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index 8ba4db1..e7c86e4 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -36,7 +36,9 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([ 30,60,65 ]  )
+        self.progress.set_steps([ 50,100 ]  )
+        self.disablepercent = False
+        self.dostep = True
     #1
     #3
     def requestingChangeSet(self):
@@ -44,10 +46,13 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
         self.backend.status(STATUS_DOWNLOAD)
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
+        if not self.disablepercent:
+            self.progress.step()
     #2
     def downloadingChangeSet(self, got, need):
         log.info("Callback UpdateSystem........ STATUS_DOWNLOAD  Changeset %.2f percent %.2f/%.2f Mbytes" % ( got*100/float(need), got/MEGA,need/MEGA) )
-        self.progress.set_subpercent( got*100 / float(need) )
+        if not self.disablepercent:
+            self.progress.set_subpercent( got*100 / float(need) )
         self.backend.percentage( self.progress.percent )
         log.info( "%s percent" % self.progress.percent)
 
@@ -57,22 +62,27 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
         self.backend.percentage(self.progress.percent)
         self.backend.status(STATUS_DEP_RESOLVE)
         self.progress.step()
-        self.backend.percentage(self.progress.percent)
-        log.info(self.progress.percent)
-
+    #5  >> request> download
     def setChangesetHunk(self, num, total):
         log.info("callback. .......... set Changeset HUnk %s/%s" % (num, total ) )
-        self.progress.step()
+        self.progress.set_subpercent( num*100/float(total) )
+        self.disablepercent = True
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
-
+        if num == total:
+            self.dostep =True
+    #6 
     def setUpdateHunk(self, hunk, hunkCount):
         log.info("callback. .......... set update HUnk %s/%s" % ( hunk, hunkCount))
-        self.progress.step()
+        if self.dostep:
+            self.progress.step()
+            self.disablepercent = True
+            self.dostep = False
+
 
         if hunk < hunkCount:
-            p = hunk / float(hunkCount) * 100.0
-            self.progress.set_subpercent(p)
+            p = hunk*100/float(hunkCount)
+            self.progress.set_subpercent( p )
         else:
             self.smallUpdate = True
 
@@ -80,77 +90,59 @@ class UpdateSystemCallback(callbacks.UpdateCallback):
         log.info(self.progress.percent)
 
     def setUpdateJob(self, job):
-        log.info("callback. .......... set update Job")
         self.currentJob = job
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
 
     def creatingRollback(self):
         #self.backend.status('Creating Rollback')
-        log.info("Callback ........ STATUS_ROLLBACK  ")
         self.backend.status(STATUS_ROLLBACK)
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
 
 
     def preparingUpdate(self, troveNum, troveCount, add=0):
-        log.info("callback ....... preparing Update  trove %s/%s" % (troveNum, troveCount) )
         #self.progress.step()
         if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
             return
 
-        if troveNum > 0 and troveCount > 0:
-            sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
-            self.progress.set_subpercent(sub_percent)
 
         self.backend.percentage(self.progress.percent)
         if troveNum > 0:
             troveNum -= 1
-        log.info("currentJob")
-        log.info(self.currentJob[troveNum])
         job = self.currentJob[troveNum]
         name = job[0]
         oldVersion, oldFlavor = job[1]
         newVersion, newFlavor = job[2]
         #log.info("JOB>>>>>>>> %s " % str(job) )
         if oldVersion and newVersion:
-            log.info("Callback ........ STATUS_UPDATE preparing Update ")
             self.backend.status(STATUS_UPDATE)
             package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             self.backend.package(package_id, INFO_UPDATING, '')
         elif oldVersion and not newVersion:
-            log.info("Callback ........ STATUS_REMOVE preparing Update ")
             self.backend.status(STATUS_REMOVE)
             package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
             self.backend.package(package_id, INFO_REMOVING, '')
         elif not oldVersion and newVersion:
-            log.info("Callback ........ STATUS_INSTALL preparing Update")
             self.backend.status(STATUS_INSTALL)
             package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             self.backend.package(package_id, INFO_INSTALLING, '')
         log.info(self.progress.percent)
 
     def creatingDatabaseTransaction(self, troveNum, troveCount):
-        log.info("callback. .......... creating Database Transactions")
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
         self.preparingUpdate(troveNum, troveCount, add=troveCount)
 
     def committingTransaction(self):
         #self.backend.status('Committing Transaction')
-        log.info("Callback ........ STATUS_COMMIT  transactions ")
 
         self.backend.status(STATUS_COMMIT)
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
 
     def updateDone(self):
         log.info("callback. ..........  update done")
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         self.currentJob = None
         log.info(self.progress.percent)
commit 531ad7f4bb6779d4f1af5d884a8fc3b88006dc42
Author: Igor Pires Soares <igorsoares at gmail.com>
Date:   Sat Feb 21 01:04:10 2009 +0000

    Updated Brazilian Portuguese translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/pt_BR.po b/po/pt_BR.po
index 2cc76e0..e27483e 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -8,8 +8,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PackageKit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-02-17 08:37+0000\n"
-"PO-Revision-Date: 2009-02-18 00:44-0300\n"
+"POT-Creation-Date: 2009-02-18 13:42+0000\n"
+"PO-Revision-Date: 2009-02-19 15:19-0300\n"
 "Last-Translator: Igor Pires Soares <igor at projetofedora.org>\n"
 "Language-Team: Brazilian Portuguese <fedora-trans-pt_br at redhat.com>\n"
 "MIME-Version: 1.0\n"
@@ -503,159 +503,164 @@ msgstr "Subcomandos:"
 
 #. TRANSLATORS: command line argument, if we should show debugging information
 #. TRANSLATORS: if we should show debugging data
-#: ../client/pk-console.c:1750
+#: ../client/pk-console.c:1752
 #: ../client/pk-generate-pack.c:185
-#: ../client/pk-monitor.c:115
+#: ../client/pk-monitor.c:125
 #: ../contrib/command-not-found/pk-command-not-found.c:510
 #: ../src/pk-main.c:199
 msgid "Show extra debugging information"
 msgstr "Mostrar informações extras de depuração"
 
 #. TRANSLATORS: command line argument, just show the version string
-#: ../client/pk-console.c:1753
-#: ../client/pk-monitor.c:117
+#: ../client/pk-console.c:1755
+#: ../client/pk-monitor.c:127
 msgid "Show the program version and exit"
 msgstr "Mostrar a versão do programa e sair"
 
 #. TRANSLATORS: command line argument, use a filter to narrow down results
-#: ../client/pk-console.c:1756
+#: ../client/pk-console.c:1758
 msgid "Set the filter, e.g. installed"
 msgstr "Definir o filtro, p. ex.: instalados"
 
 #. TRANSLATORS: command line argument, work asynchronously
-#: ../client/pk-console.c:1759
+#: ../client/pk-console.c:1761
 msgid "Exit without waiting for actions to complete"
 msgstr "Sair sem esperar pelo término das ações"
 
 #. TRANSLATORS: This is when we could not connect to the system bus, and is fatal
-#: ../client/pk-console.c:1786
+#: ../client/pk-console.c:1788
 msgid "This tool could not connect to system DBUS."
 msgstr "Esta ferramenta não pôde conectar ao DBUS do sistema."
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1873
+#: ../client/pk-console.c:1875
 msgid "The filter specified was invalid"
 msgstr "O filtro especificado era inválido"
 
 #. TRANSLATORS: a search type can be name, details, file, etc
-#: ../client/pk-console.c:1891
+#: ../client/pk-console.c:1893
 msgid "A search type is required, e.g. name"
 msgstr "Um tipo de pesquisa é requerido, p. ex. nome"
 
 #. TRANSLATORS: the user needs to provide a search term
-#: ../client/pk-console.c:1897
-#: ../client/pk-console.c:1905
-#: ../client/pk-console.c:1913
-#: ../client/pk-console.c:1921
+#: ../client/pk-console.c:1899
+#: ../client/pk-console.c:1907
+#: ../client/pk-console.c:1915
+#: ../client/pk-console.c:1923
 msgid "A search term is required"
 msgstr "Um termo de pesquisa é requerido"
 
 #. TRANSLATORS: the search type was provided, but invalid
-#: ../client/pk-console.c:1927
+#: ../client/pk-console.c:1929
 msgid "Invalid search type"
 msgstr "Tipo de pesquisa inválido"
 
 #. TRANSLATORS: the user did not specify what they wanted to install
-#: ../client/pk-console.c:1933
+#: ../client/pk-console.c:1935
 msgid "A package name or filename to install is required"
 msgstr "O nome do pacote ou arquivo é requerido"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1941
+#: ../client/pk-console.c:1943
 msgid "A type, key_id and package_id are required"
 msgstr "Um tipo, key_id e package_id são requeridos"
 
 #. TRANSLATORS: the user did not specify what they wanted to remove
-#: ../client/pk-console.c:1949
+#: ../client/pk-console.c:1951
 msgid "A package name to remove is required"
 msgstr "O nome do pacote para remoção é requerido"
 
 #. TRANSLATORS: the user did not specify anything about what to download or where
-#: ../client/pk-console.c:1956
+#: ../client/pk-console.c:1958
 msgid "A destination directory and then the package names to download are required"
 msgstr "O diretório de destino seguido dos nomes dos pacotes a serem baixados é requerido"
 
 #. TRANSLATORS: the directory does not exist, so we can't continue
-#: ../client/pk-console.c:1962
+#: ../client/pk-console.c:1964
 msgid "Directory not found"
 msgstr "Diretório não encontrado"
 
 #. TRANSLATORS: geeky error, 99.9999% of users won't see this
-#: ../client/pk-console.c:1969
+#: ../client/pk-console.c:1971
 msgid "A licence identifier (eula-id) is required"
 msgstr "Um identificador de licença (eula-id) é requerido"
 
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1980
+msgid "A transaction identifier (tid) is required"
+msgstr "Um identificador de transação (tid) é requerido"
+
 #. TRANSLATORS: The user did not specify a package name
-#: ../client/pk-console.c:1986
+#: ../client/pk-console.c:1996
 msgid "A package name to resolve is required"
 msgstr "O nome de pacote a ser analisado é requerido"
 
 #. TRANSLATORS: The user did not specify a repository (software source) name
-#: ../client/pk-console.c:1994
-#: ../client/pk-console.c:2002
+#: ../client/pk-console.c:2004
+#: ../client/pk-console.c:2012
 msgid "A repository name is required"
 msgstr "O nome do repositório é requerido"
 
 #. TRANSLATORS: The user didn't provide any data
-#: ../client/pk-console.c:2010
+#: ../client/pk-console.c:2020
 msgid "A repo name, parameter and value are required"
 msgstr "Um nome de repositório, parâmetro e um valor são requeridos"
 
 #. TRANSLATORS: The user didn't specify what action to use
-#: ../client/pk-console.c:2023
+#: ../client/pk-console.c:2033
 msgid "An action, e.g. 'update-system' is required"
 msgstr "Uma ação, p. ex. \"update-system\" é requerida"
 
 #. TRANSLATORS: The user specified an invalid action
-#: ../client/pk-console.c:2029
+#: ../client/pk-console.c:2039
 msgid "A correct role is required"
 msgstr "Um modo correto é requerido"
 
 #. TRANSLATORS: we keep a database updated with the time that an action was last executed
-#: ../client/pk-console.c:2035
+#: ../client/pk-console.c:2045
 msgid "Failed to get the time since this action was last completed"
 msgstr "Falha ao obter o tempo em que essa ação foi completada pela última vez"
 
 #. TRANSLATORS: The user did not provide a package name
 #. TRANSLATORS: This is when the user fails to supply the package name
-#: ../client/pk-console.c:2044
-#: ../client/pk-console.c:2055
-#: ../client/pk-console.c:2063
-#: ../client/pk-console.c:2079
-#: ../client/pk-console.c:2087
+#: ../client/pk-console.c:2054
+#: ../client/pk-console.c:2065
+#: ../client/pk-console.c:2073
+#: ../client/pk-console.c:2089
+#: ../client/pk-console.c:2097
 #: ../client/pk-generate-pack.c:241
 msgid "A package name is required"
 msgstr "O nome do pacote é requerido"
 
 #. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
-#: ../client/pk-console.c:2071
+#: ../client/pk-console.c:2081
 msgid "A package provide string is required"
 msgstr "É necessário especificar o que o pacote fornece"
 
 #. TRANSLATORS: The user didn't specify a filename to create as a list
-#: ../client/pk-console.c:2095
+#: ../client/pk-console.c:2105
 msgid "A list file name to create is required"
 msgstr "O nome de arquivo da lista a ser criada é requerido"
 
 #. TRANSLATORS: The user didn't specify a filename to open as a list
-#: ../client/pk-console.c:2104
-#: ../client/pk-console.c:2113
+#: ../client/pk-console.c:2114
+#: ../client/pk-console.c:2123
 msgid "A list file to open is required"
 msgstr "Uma lista de arquivos a serem abertos é requerida"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:2166
+#: ../client/pk-console.c:2176
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "A opção \"%s\" não é suportada"
 
 #. TRANSLATORS: User does not have permission to do this
-#: ../client/pk-console.c:2179
+#: ../client/pk-console.c:2189
 msgid "Incorrect privileges for this operation"
 msgstr "Privilégios incorretos para esta operação"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:2182
+#: ../client/pk-console.c:2192
 msgid "Command failed"
 msgstr "O comando falhou"
 
@@ -770,7 +775,7 @@ msgid "Failed to create '%s': %s"
 msgstr "Falha ao criar \"%s\": %s"
 
 #. TRANSLATORS: this is a program that monitors PackageKit
-#: ../client/pk-monitor.c:133
+#: ../client/pk-monitor.c:143
 msgid "PackageKit Monitor"
 msgstr "Monitor do PackageKit"
 
commit 8bdf46db3153c3f3756f464c301179d198abc909
Author: Piotr DrÄ…g <piotrdrag at gmail.com>
Date:   Fri Feb 20 23:59:37 2009 +0000

    Updated Polish translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/pl.po b/po/pl.po
index dc85e0f..13e8e73 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -5,8 +5,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: pl\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-15 16:57+0000\n"
-"PO-Revision-Date: 2009-01-16 20:32+0100\n"
+"POT-Creation-Date: 2009-02-21 00:57+0100\n"
+"PO-Revision-Date: 2009-02-21 00:59+0100\n"
 "Last-Translator: Piotr DrÄ…g <piotrdrag at gmail.com>\n"
 "Language-Team: Polish <pl at li.org>\n"
 "MIME-Version: 1.0\n"
@@ -29,11 +29,11 @@ msgid "Succeeded"
 msgstr "Powodzenie"
 
 #. TRANSLATORS: if the repo is enabled
-#: ../client/pk-console.c:234 ../client/pk-console.c:377
+#: ../client/pk-console.c:234 ../client/pk-console.c:401
 msgid "True"
 msgstr "Prawda"
 
-#: ../client/pk-console.c:234 ../client/pk-console.c:377
+#: ../client/pk-console.c:234 ../client/pk-console.c:401
 msgid "False"
 msgstr "Fałsz"
 
@@ -91,7 +91,7 @@ msgstr "Typ"
 
 #. TRANSLATORS: this is any summary text describing the upgrade
 #. TRANSLATORS: this is the summary of the group
-#: ../client/pk-console.c:297 ../client/pk-console.c:319
+#: ../client/pk-console.c:297 ../client/pk-console.c:320
 msgid "Summary"
 msgstr "Podsumowanie"
 
@@ -110,118 +110,134 @@ msgstr "Identyfikator"
 msgid "Parent"
 msgstr "Nadrzędna"
 
-#: ../client/pk-console.c:316
+#. TRANSLATORS: this is the name of the parent group
+#: ../client/pk-console.c:317
 msgid "Name"
 msgstr "Nazwa"
 
 #. TRANSLATORS: this is preferred icon for the group
-#: ../client/pk-console.c:322
+#: ../client/pk-console.c:323
 msgid "Icon"
 msgstr "Ikona"
 
 #. TRANSLATORS: this is a header for the package that can be updated
-#: ../client/pk-console.c:337
+#: ../client/pk-console.c:338
 msgid "Details about the update:"
 msgstr "Szczegóły aktualizacji:"
 
-#: ../client/pk-console.c:338
+#. TRANSLATORS: details about the update, package name and version
+#: ../client/pk-console.c:340
 msgid "Package"
 msgstr "Pakiet"
 
-#: ../client/pk-console.c:340
+#. TRANSLATORS: details about the update, any packages that this update updates
+#: ../client/pk-console.c:343
 msgid "Updates"
 msgstr "Aktualizuje"
 
-#: ../client/pk-console.c:342
+#. TRANSLATORS: details about the update, any packages that this update obsoletes
+#: ../client/pk-console.c:347
 msgid "Obsoletes"
 msgstr "Zastępuje"
 
-#: ../client/pk-console.c:344
+#. TRANSLATORS: details about the update, the vendor URLs
+#: ../client/pk-console.c:351
 msgid "Vendor"
 msgstr "Producent"
 
-#: ../client/pk-console.c:346
+#. TRANSLATORS: details about the update, the bugzilla URLs
+#: ../client/pk-console.c:355
 msgid "Bugzilla"
 msgstr "Bugzilla"
 
-#: ../client/pk-console.c:348
+#. TRANSLATORS: details about the update, the CVE URLs
+#: ../client/pk-console.c:359
 msgid "CVE"
 msgstr "CVE"
 
-#: ../client/pk-console.c:350
+#. TRANSLATORS: details about the update, if the package requires a restart
+#: ../client/pk-console.c:363
 msgid "Restart"
 msgstr "Uruchom ponownie"
 
-#: ../client/pk-console.c:352
+#. TRANSLATORS: details about the update, any description of the update
+#: ../client/pk-console.c:367
 msgid "Update text"
 msgstr "Tekst aktualizacji"
 
-#: ../client/pk-console.c:354
+#. TRANSLATORS: details about the update, the changelog for the package
+#: ../client/pk-console.c:371
 msgid "Changes"
 msgstr "Zmiany"
 
-#: ../client/pk-console.c:356
+#. TRANSLATORS: details about the update, the ongoing state of the update
+#: ../client/pk-console.c:375
 msgid "State"
 msgstr "Stan"
 
-#: ../client/pk-console.c:359
+#. TRANSLATORS: details about the update, date the update was issued
+#: ../client/pk-console.c:380
 msgid "Issued"
 msgstr "Wydano"
 
-#: ../client/pk-console.c:362
+#. TRANSLATORS: details about the update, date the update was updated
+#: ../client/pk-console.c:385
 msgid "Updated"
 msgstr "Zaktualizowano"
 
-#: ../client/pk-console.c:448 ../client/pk-console.c:450
+#: ../client/pk-console.c:472 ../client/pk-console.c:474
 msgid "Percentage"
 msgstr "Procentowo"
 
-#: ../client/pk-console.c:450
+#: ../client/pk-console.c:474
 msgid "Unknown"
 msgstr "Nieznane"
 
 #. TRANSLATORS: a package requires the system to be restarted
-#: ../client/pk-console.c:501
+#: ../client/pk-console.c:525
 msgid "System restart required by:"
 msgstr "Ponowne uruchomienie systemu jest wymagane przez:"
 
 #. TRANSLATORS: a package requires the session to be restarted
-#: ../client/pk-console.c:504
+#: ../client/pk-console.c:528
 msgid "Session restart required:"
 msgstr "Wymagane jest ponowne uruchomienie sesji:"
 
 #. TRANSLATORS: a package requires the application to be restarted
-#: ../client/pk-console.c:507
+#: ../client/pk-console.c:531
 msgid "Application restart required by:"
 msgstr "Ponowne uruchomienie programu jest wymagane przez:"
 
-#: ../client/pk-console.c:543
+#. TRANSLATORS: a package needs to restart they system
+#: ../client/pk-console.c:568
 msgid "Please restart the computer to complete the update."
 msgstr "Proszę uruchomić ponownie komputer, aby zakończyć aktualizację."
 
-#: ../client/pk-console.c:545
+#. TRANSLATORS: a package needs to restart the session
+#: ../client/pk-console.c:571
 msgid "Please logout and login to complete the update."
 msgstr "Proszę wylogować się i zalogować, aby zakończyć aktualizację."
 
-#: ../client/pk-console.c:547
+#. TRANSLATORS: a package needs to restart the application
+#: ../client/pk-console.c:574
 msgid "Please restart the application as it is being used."
 msgstr "Proszę uruchomić program ponownie, ponieważ jest używany."
 
 #. TRANSLATORS: The package is already installed on the system
-#: ../client/pk-console.c:659
+#: ../client/pk-console.c:687
 #, c-format
 msgid "The package %s is already installed"
 msgstr "Pakiet %s jest już zainstalowany"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:667
+#: ../client/pk-console.c:695
 #, c-format
 msgid "The package %s could not be installed: %s"
 msgstr "Nie można zainstalować pakietu %s: %s"
 
 #. TRANSLATORS: There was a programming error that shouldn't happen. The detailed error follows
-#: ../client/pk-console.c:692 ../client/pk-console.c:719
-#: ../client/pk-console.c:815 ../client/pk-console.c:932
+#: ../client/pk-console.c:720 ../client/pk-console.c:747
+#: ../client/pk-console.c:843 ../client/pk-console.c:960
 #: ../client/pk-tools-common.c:61 ../client/pk-tools-common.c:79
 #: ../client/pk-tools-common.c:86
 #, c-format
@@ -229,459 +245,513 @@ msgid "Internal error: %s"
 msgstr "Wewnętrzny błąd: %s"
 
 #. TRANSLATORS: There was an error installing the packages. The detailed error follows
-#: ../client/pk-console.c:700 ../client/pk-console.c:1327
+#: ../client/pk-console.c:728 ../client/pk-console.c:1355
 #, c-format
 msgid "This tool could not install the packages: %s"
 msgstr "To narzędzie nie może zainstalować pakietów: %s"
 
 #. TRANSLATORS: There was an error installing the files. The detailed error follows
-#: ../client/pk-console.c:727
+#: ../client/pk-console.c:755
 #, c-format
 msgid "This tool could not install the files: %s"
 msgstr "To narzędzie nie może zainstalować plików: %s"
 
 #. TRANSLATORS: The package name was not found in the installed list. The detailed error follows
-#: ../client/pk-console.c:783
+#: ../client/pk-console.c:811
 #, c-format
 msgid "This tool could not remove %s: %s"
 msgstr "To narzędzie nie może usunąć %s: %s"
 
 #. TRANSLATORS: There was an error removing the packages. The detailed error follows
-#: ../client/pk-console.c:806 ../client/pk-console.c:844
-#: ../client/pk-console.c:877
+#: ../client/pk-console.c:834 ../client/pk-console.c:872
+#: ../client/pk-console.c:905
 #, c-format
 msgid "This tool could not remove the packages: %s"
 msgstr "To narzędzie nie może usunąć pakietów: %s"
 
 #. TRANSLATORS: When removing, we might have to remove other dependencies
-#: ../client/pk-console.c:856
+#: ../client/pk-console.c:884
 msgid "The following packages have to be removed:"
 msgstr "Następujące pakiety muszą zostać usunięte:"
 
 #. TRANSLATORS: We are checking if it's okay to remove a list of packages
-#: ../client/pk-console.c:863
+#: ../client/pk-console.c:891
 msgid "Proceed removing additional packages?"
 msgstr "Kontynuować usuwanie dodatkowych pakietów?"
 
 #. TRANSLATORS: We did not remove any packages
-#: ../client/pk-console.c:868
+#: ../client/pk-console.c:896
 msgid "The package removal was canceled!"
 msgstr "Anulowano usunięcie pakietu!"
 
 #. TRANSLATORS: The package name was not found in any software sources
-#: ../client/pk-console.c:909
+#: ../client/pk-console.c:937
 #, c-format
 msgid "This tool could not download the package %s as it could not be found"
 msgstr "To narzędzie nie może pobrać pakietu %s, ponieważ nie można go znaleźć"
 
 #. TRANSLATORS: Could not download the packages for some reason. The detailed error follows
-#: ../client/pk-console.c:940
+#: ../client/pk-console.c:968
 #, c-format
 msgid "This tool could not download the packages: %s"
 msgstr "To narzędzie nie może pobrać pakietów: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:967 ../client/pk-console.c:976
+#: ../client/pk-console.c:995 ../client/pk-console.c:1004
 #, c-format
 msgid "This tool could not update %s: %s"
 msgstr "To narzędzie nie może zaktualizować %s: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:998 ../client/pk-console.c:1006
+#: ../client/pk-console.c:1026 ../client/pk-console.c:1034
 #, c-format
 msgid "This tool could not get the requirements for %s: %s"
 msgstr "To narzędzie nie może uzyskać wymagań dla %s: %s"
 
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
-#: ../client/pk-console.c:1028 ../client/pk-console.c:1036
+#: ../client/pk-console.c:1056 ../client/pk-console.c:1064
 #, c-format
 msgid "This tool could not get the dependencies for %s: %s"
 msgstr "To narzędzie nie może uzyskać zależności dla %s: %s"
 
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
-#: ../client/pk-console.c:1058 ../client/pk-console.c:1066
+#: ../client/pk-console.c:1086 ../client/pk-console.c:1094
 #, c-format
 msgid "This tool could not get package details for %s: %s"
 msgstr "To narzędzie nie może uzyskać szczegółów pakietu %s: %s"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:1088
+#: ../client/pk-console.c:1116
 #, c-format
 msgid "This tool could not find the files for %s: %s"
 msgstr "To narzędzie nie może znaleźć plików dla %s: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:1096
+#: ../client/pk-console.c:1124
 #, c-format
 msgid "This tool could not get the file list for %s: %s"
 msgstr "To narzędzie nie może uzyskać listy plików dla %s: %s"
 
 #. TRANSLATORS: There was an error getting the list of packages. The filename follows
-#: ../client/pk-console.c:1118
+#: ../client/pk-console.c:1146
 #, c-format
 msgid "File already exists: %s"
 msgstr "Plik już istnieje: %s"
 
 #. TRANSLATORS: follows a list of packages to install
-#: ../client/pk-console.c:1123 ../client/pk-console.c:1179
-#: ../client/pk-console.c:1254
+#: ../client/pk-console.c:1151 ../client/pk-console.c:1207
+#: ../client/pk-console.c:1282
 msgid "Getting package list"
 msgstr "Pobieranie listy pakietów"
 
 #. TRANSLATORS: There was an error getting the list of packages. The detailed error follows
-#: ../client/pk-console.c:1129 ../client/pk-console.c:1185
-#: ../client/pk-console.c:1260
+#: ../client/pk-console.c:1157 ../client/pk-console.c:1213
+#: ../client/pk-console.c:1288
 #, c-format
 msgid "This tool could not get package list: %s"
 msgstr "To narzędzie nie może pobrać listy pakietów: %s"
 
 #. TRANSLATORS: There was an error saving the list
-#: ../client/pk-console.c:1140
+#: ../client/pk-console.c:1168
 #, c-format
 msgid "Failed to save to disk"
 msgstr "Zapisanie na dysku nie powiodło się"
 
 #. TRANSLATORS: There was an error getting the list. The filename follows
-#: ../client/pk-console.c:1174 ../client/pk-console.c:1249
+#: ../client/pk-console.c:1202 ../client/pk-console.c:1277
 #, c-format
 msgid "File does not exist: %s"
 msgstr "Plik nie istnieje: %s"
 
 #. TRANSLATORS: header to a list of packages newly added
-#: ../client/pk-console.c:1206
+#: ../client/pk-console.c:1234
 msgid "Packages to add"
 msgstr "Pakiety do dodania"
 
 #. TRANSLATORS: header to a list of packages removed
-#: ../client/pk-console.c:1214
+#: ../client/pk-console.c:1242
 msgid "Packages to remove"
 msgstr "Pakiety do usunięcia"
 
 #. TRANSLATORS: We didn't find any differences
-#: ../client/pk-console.c:1282
+#: ../client/pk-console.c:1310
 #, c-format
 msgid "No new packages need to be installed"
 msgstr "Nie trzeba instalować nowych pakietów"
 
 #. TRANSLATORS: follows a list of packages to install
-#: ../client/pk-console.c:1288
+#: ../client/pk-console.c:1316
 msgid "To install"
 msgstr "Do zainstalowania"
 
 #. TRANSLATORS: searching takes some time....
-#: ../client/pk-console.c:1299
+#: ../client/pk-console.c:1327
 msgid "Searching for package: "
 msgstr "Wyszukiwanie pakietu: "
 
 #. TRANSLATORS: package was not found -- this is the end of a string ended in ...
-#: ../client/pk-console.c:1303
+#: ../client/pk-console.c:1331
 msgid "not found."
 msgstr "nie znaleziono."
 
 #. TRANSLATORS: We didn't find any packages to install
-#: ../client/pk-console.c:1314
+#: ../client/pk-console.c:1342
 #, c-format
 msgid "No packages can be found to install"
 msgstr "Nie można znaleźć pakietów do zainstalowania"
 
 #. TRANSLATORS: installing new packages from package list
-#: ../client/pk-console.c:1320
+#: ../client/pk-console.c:1348
 msgid "Installing packages"
 msgstr "Instalowanie pakietów"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:1356
+#: ../client/pk-console.c:1384
 #, c-format
 msgid "This tool could not find the update details for %s: %s"
 msgstr "To narzędzie nie może znaleźć szczegółów aktualizacji dla %s: %s"
 
 #. TRANSLATORS: There was an error getting the details about the update for the package. The detailed error follows
-#: ../client/pk-console.c:1364
+#: ../client/pk-console.c:1392
 #, c-format
 msgid "This tool could not get the update details for %s: %s"
 msgstr "To narzędzie nie może uzyskać szczegółów aktualizacji dla %s: %s"
 
 #. TRANSLATORS: This was an unhandled error, and we don't have _any_ context
-#: ../client/pk-console.c:1410
+#: ../client/pk-console.c:1438
 msgid "Error:"
 msgstr "BÅ‚Ä…d:"
 
 #. TRANSLATORS: This a list of details about the package
-#: ../client/pk-console.c:1424
+#: ../client/pk-console.c:1452
 msgid "Package description"
 msgstr "Opis pakietu"
 
 #. TRANSLATORS: This a list files contained in the package
-#: ../client/pk-console.c:1458
+#: ../client/pk-console.c:1486
 msgid "Package files"
 msgstr "Pliki pakietu"
 
 #. TRANSLATORS: This where the package has no files
-#: ../client/pk-console.c:1466
+#: ../client/pk-console.c:1494
 msgid "No files"
 msgstr "Brak plików"
 
 #. TRANSLATORS: This a request for a GPG key signature from the backend, which the client will prompt for later
-#: ../client/pk-console.c:1489
+#: ../client/pk-console.c:1517
 msgid "Repository signature required"
 msgstr "Wymagany jest podpis repozytorium"
 
 #. TRANSLATORS: This a prompt asking the user to import the security key
-#: ../client/pk-console.c:1499
+#: ../client/pk-console.c:1527
 msgid "Do you accept this signature?"
 msgstr "Zaakceptować ten podpis?"
 
 #. TRANSLATORS: This is where the user declined the security key
-#: ../client/pk-console.c:1503
+#: ../client/pk-console.c:1531
 msgid "The signature was not accepted."
 msgstr "Podpis nie został zaakceptowany."
 
 #. TRANSLATORS: This a request for a EULA
-#: ../client/pk-console.c:1537
+#: ../client/pk-console.c:1565
 msgid "End user license agreement required"
 msgstr "Licencja jest wymagana"
 
 #. TRANSLATORS: This a prompt asking the user to agree to the license
-#: ../client/pk-console.c:1544
+#: ../client/pk-console.c:1572
 msgid "Do you agree to this license?"
 msgstr "Zaakceptować tę licencję?"
 
 #. TRANSLATORS: This is where the user declined the license
-#: ../client/pk-console.c:1548
+#: ../client/pk-console.c:1576
 msgid "The license was refused."
 msgstr "Odrzucono licencjÄ™."
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1577
+#: ../client/pk-console.c:1605
 msgid "The daemon crashed mid-transaction!"
 msgstr "Demon zawiesił się w połowie transakcji!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1630
+#: ../client/pk-console.c:1658
 msgid "PackageKit Console Interface"
 msgstr "Interfejs konsoli PackageKit"
 
-#: ../client/pk-console.c:1630
+#. these are commands we can use with pkcon
+#: ../client/pk-console.c:1660
 msgid "Subcommands:"
 msgstr "Podpolecenia:"
 
-#: ../client/pk-console.c:1719 ../client/pk-generate-pack.c:184
-#: ../client/pk-monitor.c:115
+#. TRANSLATORS: command line argument, if we should show debugging information
+#. TRANSLATORS: if we should show debugging data
+#: ../client/pk-console.c:1752 ../client/pk-generate-pack.c:185
+#: ../client/pk-monitor.c:125
 #: ../contrib/command-not-found/pk-command-not-found.c:510
-#: ../src/pk-main.c:192
+#: ../src/pk-main.c:199
 msgid "Show extra debugging information"
 msgstr "Wyświetla dodatkowe informacje o debugowaniu"
 
-#: ../client/pk-console.c:1721 ../client/pk-monitor.c:117
+#. TRANSLATORS: command line argument, just show the version string
+#: ../client/pk-console.c:1755 ../client/pk-monitor.c:127
 msgid "Show the program version and exit"
 msgstr "Wyświetla wersję programu i wyłącza"
 
-#: ../client/pk-console.c:1723
+#. TRANSLATORS: command line argument, use a filter to narrow down results
+#: ../client/pk-console.c:1758
 msgid "Set the filter, e.g. installed"
 msgstr "Ustawia filtr, np. zainstalowane"
 
-#: ../client/pk-console.c:1725
+#. TRANSLATORS: command line argument, work asynchronously
+#: ../client/pk-console.c:1761
 msgid "Exit without waiting for actions to complete"
 msgstr "Wyłącza bez oczekiwania na zakończenie działań"
 
 #. TRANSLATORS: This is when we could not connect to the system bus, and is fatal
-#: ../client/pk-console.c:1752
+#: ../client/pk-console.c:1788
 msgid "This tool could not connect to system DBUS."
 msgstr "To narzędzie nie może połączyć się z systemowym D-Bus."
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1839
+#: ../client/pk-console.c:1875
 msgid "The filter specified was invalid"
 msgstr "Podany filtr jest nieprawidłowy"
 
-#: ../client/pk-console.c:1856
-msgid "You need to specify a search type, e.g. name"
-msgstr "Należy podać typ wyszukiwania, np. po nazwie"
+#. TRANSLATORS: a search type can be name, details, file, etc
+#: ../client/pk-console.c:1893
+msgid "A search type is required, e.g. name"
+msgstr "Wymagany jest typ wyszukiwania, np. nazwa"
 
-#: ../client/pk-console.c:1861 ../client/pk-console.c:1868
-#: ../client/pk-console.c:1875 ../client/pk-console.c:1882
-#: ../client/pk-console.c:1990 ../client/pk-console.c:2000
-#: ../client/pk-console.c:2007 ../client/pk-console.c:2014
-msgid "You need to specify a search term"
-msgstr "Należy podać termin wyszukiwania"
+#. TRANSLATORS: the user needs to provide a search term
+#: ../client/pk-console.c:1899 ../client/pk-console.c:1907
+#: ../client/pk-console.c:1915 ../client/pk-console.c:1923
+msgid "A search term is required"
+msgstr "Wymagany jest wyszukiwany termin"
 
-#: ../client/pk-console.c:1887
+#. TRANSLATORS: the search type was provided, but invalid
+#: ../client/pk-console.c:1929
 msgid "Invalid search type"
 msgstr "Nieprawidłowy typ wyszukiwania"
 
-#: ../client/pk-console.c:1892
-msgid "You need to specify a package or file to install"
-msgstr "Należy podać pakiet lub plik do zainstalowania"
+#. TRANSLATORS: the user did not specify what they wanted to install
+#: ../client/pk-console.c:1935
+msgid "A package name or filename to install is required"
+msgstr "Wymagana jest nazwa pakietu lub pliku do zainstalowania"
 
-#: ../client/pk-console.c:1899
-msgid "You need to specify a type, key_id and package_id"
-msgstr "Należy podać typ, key_id i package_id"
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1943
+msgid "A type, key_id and package_id are required"
+msgstr "Wymagany jest typ, key_id i package_id"
 
-#: ../client/pk-console.c:1906
-msgid "You need to specify a package to remove"
-msgstr "Należy podać pakiet do usunięcia"
+#. TRANSLATORS: the user did not specify what they wanted to remove
+#: ../client/pk-console.c:1951
+msgid "A package name to remove is required"
+msgstr "Wymagana jest nazwa pakietu do usunięcia"
 
-#: ../client/pk-console.c:1912
+#. TRANSLATORS: the user did not specify anything about what to download or where
+#: ../client/pk-console.c:1958
 msgid ""
-"You need to specify the destination directory and then the packages to "
-"download"
-msgstr "Należy podać katalog docelowy, a następnie pakiety do pobrania"
+"A destination directory and then the package names to download are required"
+msgstr "Wymagany jest katalog docelowy, a następnie nazwy pakietów do pobrania"
 
-#: ../client/pk-console.c:1917
+#. TRANSLATORS: the directory does not exist, so we can't continue
+#: ../client/pk-console.c:1964
 msgid "Directory not found"
 msgstr "Nie znaleziono katalogu"
 
-#: ../client/pk-console.c:1923
-msgid "You need to specify a licence identifier (eula-id)"
-msgstr "Należy podać identyfikator licencji (eula-id)"
-
-#: ../client/pk-console.c:1939
-msgid "You need to specify a package name to resolve"
-msgstr "Należy podać nazwę pakietu do rozwiązania"
-
-#: ../client/pk-console.c:1946 ../client/pk-console.c:1953
-msgid "You need to specify a repository name"
-msgstr "Należy podać nazwę repozytorium"
-
-#: ../client/pk-console.c:1960
-msgid "You need to specify a repo name/parameter and value"
-msgstr "Należy podać nazwę/parametr repozytorium i wartość"
-
-#: ../client/pk-console.c:1972
-msgid "You need to specify an action, e.g. 'update-system'"
-msgstr "Należy podać działanie, np. \"update-system\""
-
-#: ../client/pk-console.c:1977
-msgid "You need to specify a correct role"
-msgstr "Należy podać poprawną rolę"
-
-#: ../client/pk-console.c:1982
-msgid "Failed to get last time"
-msgstr "Uzyskanie ostatniego czasu nie powiodło się"
-
-#: ../client/pk-console.c:2021
-msgid "You need to specify a package to find the details for"
-msgstr "Należy podać pakiet do znalezienia szczegółów dla"
-
-#: ../client/pk-console.c:2028
-msgid "You need to specify a package to find the files for"
-msgstr "Należy podać pakiet do znalezienia plików dla"
-
-#: ../client/pk-console.c:2035
-msgid "You need to specify a list file to create"
-msgstr "Należy podać plik listy do utworzenia"
-
-#: ../client/pk-console.c:2043 ../client/pk-console.c:2051
-msgid "You need to specify a list file to open"
-msgstr "Należy podać plik listy do otwarcia"
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1971
+msgid "A licence identifier (eula-id) is required"
+msgstr "Wymagany jest identyfikator licencji (eula-id)"
+
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1980
+msgid "A transaction identifier (tid) is required"
+msgstr "Wymagany jest identyfikator transakcji (tid)"
+
+#. TRANSLATORS: The user did not specify a package name
+#: ../client/pk-console.c:1996
+msgid "A package name to resolve is required"
+msgstr "Wymagana jest nazwa pakietu do rozwiÄ…zania"
+
+#. TRANSLATORS: The user did not specify a repository (software source) name
+#: ../client/pk-console.c:2004 ../client/pk-console.c:2012
+msgid "A repository name is required"
+msgstr "Wymagana jest nazwa repozytorium"
+
+#. TRANSLATORS: The user didn't provide any data
+#: ../client/pk-console.c:2020
+msgid "A repo name, parameter and value are required"
+msgstr "Wymagana jest nazwa, parametr i wartość repozytorium"
+
+#. TRANSLATORS: The user didn't specify what action to use
+#: ../client/pk-console.c:2033
+msgid "An action, e.g. 'update-system' is required"
+msgstr "Wymagane jest działanie, np. \"update-system\""
+
+#. TRANSLATORS: The user specified an invalid action
+#: ../client/pk-console.c:2039
+msgid "A correct role is required"
+msgstr "Wymagana jest bieżąca rola"
+
+#. TRANSLATORS: we keep a database updated with the time that an action was last executed
+#: ../client/pk-console.c:2045
+msgid "Failed to get the time since this action was last completed"
+msgstr ""
+"Uzyskanie czasu od ostatniego zakończenia tego działania nie powiodło się"
+
+#. TRANSLATORS: The user did not provide a package name
+#. TRANSLATORS: This is when the user fails to supply the package name
+#: ../client/pk-console.c:2054 ../client/pk-console.c:2065
+#: ../client/pk-console.c:2073 ../client/pk-console.c:2089
+#: ../client/pk-console.c:2097 ../client/pk-generate-pack.c:241
+msgid "A package name is required"
+msgstr "Wymagana jest nazwa pakietu"
+
+#. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
+#: ../client/pk-console.c:2081
+msgid "A package provide string is required"
+msgstr "Wymagany jest łańcuch dostarczania pakietu"
+
+#. TRANSLATORS: The user didn't specify a filename to create as a list
+#: ../client/pk-console.c:2105
+msgid "A list file name to create is required"
+msgstr "Wymagana jest lista nazw plików do utworzenia"
+
+#. TRANSLATORS: The user didn't specify a filename to open as a list
+#: ../client/pk-console.c:2114 ../client/pk-console.c:2123
+msgid "A list file to open is required"
+msgstr "Wymagana jest lista plików do otwarcia"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:2104
+#: ../client/pk-console.c:2176
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "Opcja \"%s\" nie jest obsługiwana"
 
 #. TRANSLATORS: User does not have permission to do this
-#: ../client/pk-console.c:2117
-msgid "You don't have the necessary privileges for this operation"
-msgstr "Nie posiadasz niezbędnych uprawnień dla tej operacji"
+#: ../client/pk-console.c:2189
+msgid "Incorrect privileges for this operation"
+msgstr "Niepoprawne uprawnienia dla tego działania"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:2120
+#: ../client/pk-console.c:2192
 msgid "Command failed"
 msgstr "Polecenie nie powiodło się"
 
 #. TRANSLATORS: This is the state of the transaction
-#: ../client/pk-generate-pack.c:100
+#: ../client/pk-generate-pack.c:101
 msgid "Downloading"
 msgstr "Pobieranie"
 
 #. TRANSLATORS: This is when the main packages are being downloaded
-#: ../client/pk-generate-pack.c:120
+#: ../client/pk-generate-pack.c:121
 msgid "Downloading packages"
 msgstr "Pobieranie pakietów"
 
 #. TRANSLATORS: This is when the dependency packages are being downloaded
-#: ../client/pk-generate-pack.c:125
+#: ../client/pk-generate-pack.c:126
 msgid "Downloading dependencies"
 msgstr "Pobieranie zależności"
 
-#: ../client/pk-generate-pack.c:186
+#. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
+#: ../client/pk-generate-pack.c:188
 msgid "Set the file name of dependencies to be excluded"
 msgstr "Proszę ustawić nazwy plików zależności do wykluczenia"
 
-#: ../client/pk-generate-pack.c:188
-msgid "The output directory (the current directory is used if ommitted)"
+#. TRANSLATORS: the output location
+#: ../client/pk-generate-pack.c:191
+msgid ""
+"The output file or directory (the current directory is used if ommitted)"
 msgstr ""
-"Katalog wyjścia (użyty zostanie bieżący katalog, jeśli zostanie pominięty)"
+"Plik lub katalog wyjścia (użyty zostanie bieżący katalog, jeśli zostanie "
+"pominięte)"
 
-#: ../client/pk-generate-pack.c:190
+#. TRANSLATORS: put a list of packages in the pack
+#: ../client/pk-generate-pack.c:194
 msgid "The package to be put into the service pack"
 msgstr "Pakiet do umieszczenia w pakiecie serwisowym"
 
-#: ../client/pk-generate-pack.c:192
+#. TRANSLATORS: put all pending updates in the pack
+#: ../client/pk-generate-pack.c:197
 msgid "Put all updates available in the service pack"
 msgstr "Wszystkie dostępne aktualizacje w pakiecie serwisowym"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:220
+#: ../client/pk-generate-pack.c:225
 msgid "Neither --package or --updates option selected."
 msgstr "Nie wybrano żadnej z opcji --package lub --updates."
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:228
+#: ../client/pk-generate-pack.c:233
 msgid "Both options selected."
 msgstr "Wybrano obie opcje."
 
+#. TRANSLATORS: This is when the user fails to supply the output
+#: ../client/pk-generate-pack.c:249
+msgid "A output directory or file name is required"
+msgstr "Wymagany jest katalog lub nazwa pliku wyjścia"
+
+#. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
+#. TRANSLATORS: This is when the backend doesn't have the capability to download
+#: ../client/pk-generate-pack.c:267 ../client/pk-generate-pack.c:273
+msgid "The package manager cannot perform this type of operation."
+msgstr "Menedżer pakietów nie może wykonać tego typu działania."
+
+#. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
+#: ../client/pk-generate-pack.c:285
+msgid "If specifying a file, the service pack name must end with"
+msgstr "Jeśli podano plik, nazwa pakietu serwisowego musi kończyć się"
+
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:261
+#: ../client/pk-generate-pack.c:301
 msgid "A pack with the same name already exists, do you want to overwrite it?"
 msgstr "Pakiet serwisowy o tej samej nazwie już istnieje, zastąpić go?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:264
+#: ../client/pk-generate-pack.c:304
 msgid "The pack was not overwritten."
 msgstr "Pakiet nie został zastąpiony."
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:276
+#: ../client/pk-generate-pack.c:317
 msgid "Failed to create directory:"
 msgstr "Utworzenie katalogu nie powiodło się:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:285
+#: ../client/pk-generate-pack.c:327
 msgid "Failed to open package list."
 msgstr "Otwarcie listy pakietów nie powiodło się."
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:295
+#: ../client/pk-generate-pack.c:338
 msgid "Finding package name."
 msgstr "Wyszukiwanie nazwy pakietu."
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:299
+#: ../client/pk-generate-pack.c:342
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "Nie można znaleźć pakietu \"%s\": %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:315
+#: ../client/pk-generate-pack.c:359
 msgid "Creating service pack..."
 msgstr "Tworzenie pakietu serwisowego..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:322
+#: ../client/pk-generate-pack.c:366
 #, c-format
 msgid "Service pack created '%s'"
 msgstr "Utworzono pakiet serwisowy \"%s\""
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:326
+#: ../client/pk-generate-pack.c:371
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Utworzenie \"%s\" nie powiodło się: %s"
 
-#: ../client/pk-monitor.c:132
+#. TRANSLATORS: this is a program that monitors PackageKit
+#: ../client/pk-monitor.c:143
 msgid "PackageKit Monitor"
 msgstr "Monitor PackageKit"
 
@@ -797,6 +867,7 @@ msgstr "Zainstalowana wersja"
 msgid "Run version %s now"
 msgstr "Uruchom wersjÄ™ %s"
 
+#. TRANSLATORS: run the application now
 #: ../contrib/browser-plugin/src/contents.cpp:324
 msgid "Run now"
 msgstr "Uruchom teraz"
@@ -940,21 +1011,25 @@ msgstr "Oznaczenie klucza używanego do podpisywania pakietów jako zaufanego"
 msgid "Update packages"
 msgstr "Aktualizacja pakietów"
 
-#: ../src/pk-main.c:86
+#. TRANSLATORS: failed due to DBus security
+#: ../src/pk-main.c:87
 msgid "Startup failed due to security policies on this machine."
 msgstr ""
 "Uruchomienie nie powiodło się z powodu polityk bezpieczeństwa tego komputera."
 
-#: ../src/pk-main.c:87
+#. TRANSLATORS: only two ways this can fail...
+#: ../src/pk-main.c:89
 msgid "This can happen for two reasons:"
 msgstr "Mogło się to wydarzyć z dwóch powodów:"
 
-#: ../src/pk-main.c:88
+#. TRANSLATORS: only allowed to be owned by root
+#: ../src/pk-main.c:91
 msgid "The correct user is not launching the executable (usually root)"
 msgstr ""
 "Prawidłowy użytkownik nie uruchamiania pliku wykonywalnego (zwykle root)"
 
-#: ../src/pk-main.c:89
+#. TRANSLATORS: or we are installed in a prefix
+#: ../src/pk-main.c:93
 msgid ""
 "The org.freedesktop.PackageKit.conf file is not installed in the system "
 "directory:"
@@ -962,39 +1037,48 @@ msgstr ""
 "Plik org.freedesktop.PackageKit.conf nie jest zainstalowany w katalogu "
 "systemowym:"
 
-#: ../src/pk-main.c:188
+#. TRANSLATORS: a backend is the system package tool, e.g. yum, apt
+#: ../src/pk-main.c:193
 msgid "Packaging backend to use, e.g. dummy"
 msgstr "Używany moduł przetwarzający, np. dummy"
 
-#: ../src/pk-main.c:190
+#. TRANSLATORS: if we should run in the background
+#: ../src/pk-main.c:196
 msgid "Daemonize and detach from the terminal"
 msgstr "Tworzy demona i odłącza z terminala"
 
-#: ../src/pk-main.c:194
+#. TRANSLATORS: if we should not monitor how long we are inactive for
+#: ../src/pk-main.c:202
 msgid "Disable the idle timer"
 msgstr "Wyłącza licznik czasu bezczynności"
 
-#: ../src/pk-main.c:196
+#. TRANSLATORS: show version
+#: ../src/pk-main.c:205
 msgid "Show version and exit"
 msgstr "Wyświetla wersję i wyłącza"
 
-#: ../src/pk-main.c:198
+#. TRANSLATORS: exit after we've started up, used for user profiling
+#: ../src/pk-main.c:208
 msgid "Exit after a small delay"
 msgstr "Wyłącza po małej przerwie"
 
-#: ../src/pk-main.c:200
+#. TRANSLATORS: exit straight away, used for automatic profiling
+#: ../src/pk-main.c:211
 msgid "Exit after the engine has loaded"
 msgstr "Wyłącza po wczytaniu mechanizmu"
 
-#: ../src/pk-main.c:214
+#. TRANSLATORS: describing the service that is running
+#: ../src/pk-main.c:226
 msgid "PackageKit service"
 msgstr "Usługa PackageKit"
 
-#: ../src/pk-main.c:250
+#. TRANSLATORS: fatal error, dbus is not running
+#: ../src/pk-main.c:263
 msgid "Cannot connect to the system bus"
 msgstr "Nie można połączyć się z magistralą systemową"
 
-#: ../src/pk-main.c:299
+#. TRANSLATORS: cannot register on system bus, unknown reason
+#: ../src/pk-main.c:313
 #, c-format
 msgid "Error trying to start: %s\n"
 msgstr "Błąd podczas próbowania uruchomienia: %s\n"
commit 4aab96ee5f0aaa263cdb0d449130dfe40545e62b
Author: Domingo Becker <domingobecker at gmail.com>
Date:   Fri Feb 20 23:02:19 2009 +0000

    updated Spanish translation
    
    Transmitted-via: Transifex (translate.fedoraproject.org)

diff --git a/po/es.po b/po/es.po
index 8880f23..dfb9f7a 100644
--- a/po/es.po
+++ b/po/es.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: packagekit\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-01-15 16:57+0000\n"
-"PO-Revision-Date: 2008-12-12 09:37-0300\n"
+"POT-Creation-Date: 2009-02-18 13:42+0000\n"
+"PO-Revision-Date: 2009-02-20 15:45-0300\n"
 "Last-Translator: Domingo Becker <domingobecker at gmail.com>\n"
 "Language-Team: Spanish <fedora-trans-es at redhat.com>\n"
 "MIME-Version: 1.0\n"
@@ -19,691 +19,765 @@ msgstr ""
 #. TRANSLATORS: this is an atomic transaction
 #: ../client/pk-console.c:230
 msgid "Transaction"
-msgstr ""
+msgstr "Transacción"
 
 #. TRANSLATORS: this is the time the transaction was started in system timezone
 #: ../client/pk-console.c:232
 msgid "System time"
-msgstr ""
+msgstr "Hora del sistema"
 
 #. TRANSLATORS: this is if the transaction succeeded or not
 #: ../client/pk-console.c:234
 msgid "Succeeded"
-msgstr ""
+msgstr "Existosa"
 
 #. TRANSLATORS: if the repo is enabled
-#: ../client/pk-console.c:234 ../client/pk-console.c:377
+#: ../client/pk-console.c:234
+#: ../client/pk-console.c:401
 msgid "True"
-msgstr ""
+msgstr "Verdadero"
 
-#: ../client/pk-console.c:234 ../client/pk-console.c:377
+#: ../client/pk-console.c:234
+#: ../client/pk-console.c:401
 msgid "False"
-msgstr ""
+msgstr "Falso"
 
 #. TRANSLATORS: this is the transactions role, e.g. "update-system"
 #: ../client/pk-console.c:236
 msgid "Role"
-msgstr ""
+msgstr "Rol"
 
 #. TRANSLATORS: this is The duration of the transaction
 #: ../client/pk-console.c:241
 msgid "Duration"
-msgstr ""
+msgstr "Duración"
 
 #: ../client/pk-console.c:241
 msgid "(seconds)"
-msgstr ""
+msgstr "(segundos)"
 
 #. TRANSLATORS: this is The command line used to do the action
 #: ../client/pk-console.c:245
-#, fuzzy
 msgid "Command line"
-msgstr "Commando falló"
+msgstr "Línea de Comando"
 
 #. TRANSLATORS: this is the user ID of the user that started the action
 #: ../client/pk-console.c:247
 msgid "User ID"
-msgstr ""
+msgstr "ID del Usuario"
 
 #. TRANSLATORS: this is the username, e.g. hughsie
 #: ../client/pk-console.c:254
 msgid "Username"
-msgstr ""
+msgstr "Nombre de Usuario"
 
 #. TRANSLATORS: this is the users real name, e.g. "Richard Hughes"
 #: ../client/pk-console.c:258
 msgid "Real name"
-msgstr ""
+msgstr "Nombre real"
 
 #: ../client/pk-console.c:266
-#, fuzzy
 msgid "Affected packages:"
-msgstr "Actualizar paquete"
+msgstr "Paquete afectados:"
 
 #: ../client/pk-console.c:268
 msgid "Affected packages: None"
-msgstr ""
+msgstr "Paquetes afectados: Ninguno"
 
 #. TRANSLATORS: this is the distro, e.g. Fedora 10
 #: ../client/pk-console.c:293
 msgid "Distribution"
-msgstr ""
+msgstr "Distribución"
 
 #. TRANSLATORS: this is type of update, stable or testing
 #: ../client/pk-console.c:295
 msgid "Type"
-msgstr ""
+msgstr "Tipo"
 
 #. TRANSLATORS: this is any summary text describing the upgrade
 #. TRANSLATORS: this is the summary of the group
-#: ../client/pk-console.c:297 ../client/pk-console.c:319
+#: ../client/pk-console.c:297
+#: ../client/pk-console.c:320
 msgid "Summary"
-msgstr ""
+msgstr "Resúmen"
 
 #. TRANSLATORS: this is the group category name
 #: ../client/pk-console.c:309
 msgid "Category"
-msgstr ""
+msgstr "categoría"
 
 #. TRANSLATORS: this is group identifier
 #: ../client/pk-console.c:311
 msgid "ID"
-msgstr ""
+msgstr "ID"
 
 #. TRANSLATORS: this is the parent group
 #: ../client/pk-console.c:314
 msgid "Parent"
-msgstr ""
+msgstr "Padre"
 
-#: ../client/pk-console.c:316
+#. TRANSLATORS: this is the name of the parent group
+#: ../client/pk-console.c:317
 msgid "Name"
-msgstr ""
+msgstr "Nombre"
 
 #. TRANSLATORS: this is preferred icon for the group
-#: ../client/pk-console.c:322
+#: ../client/pk-console.c:323
 msgid "Icon"
-msgstr ""
+msgstr "Icono"
 
 #. TRANSLATORS: this is a header for the package that can be updated
-#: ../client/pk-console.c:337
+#: ../client/pk-console.c:338
 msgid "Details about the update:"
 msgstr "Detalles acerca de la actualización:"
 
-#: ../client/pk-console.c:338
-#, fuzzy
+#. TRANSLATORS: details about the update, package name and version
+#: ../client/pk-console.c:340
 msgid "Package"
-msgstr "Archivos del paquete"
+msgstr "Paquete"
 
-#: ../client/pk-console.c:340
-#, fuzzy
+#. TRANSLATORS: details about the update, any packages that this update updates
+#: ../client/pk-console.c:343
 msgid "Updates"
-msgstr "Actualizar paquete"
+msgstr "Actualizaciones"
 
-#: ../client/pk-console.c:342
+#. TRANSLATORS: details about the update, any packages that this update obsoletes
+#: ../client/pk-console.c:347
 msgid "Obsoletes"
-msgstr ""
+msgstr "Sustituye"
 
-#: ../client/pk-console.c:344
+#. TRANSLATORS: details about the update, the vendor URLs
+#: ../client/pk-console.c:351
 msgid "Vendor"
-msgstr ""
+msgstr "Vendedor"
 
-#: ../client/pk-console.c:346
+#. TRANSLATORS: details about the update, the bugzilla URLs
+#: ../client/pk-console.c:355
 msgid "Bugzilla"
-msgstr ""
+msgstr "Bugzilla"
 
-#: ../client/pk-console.c:348
+#. TRANSLATORS: details about the update, the CVE URLs
+#: ../client/pk-console.c:359
 msgid "CVE"
-msgstr ""
+msgstr "CVE"
 
-#: ../client/pk-console.c:350
+#. TRANSLATORS: details about the update, if the package requires a restart
+#: ../client/pk-console.c:363
 msgid "Restart"
-msgstr ""
+msgstr "Reiniciar"
 
-#: ../client/pk-console.c:352
-#, fuzzy
+#. TRANSLATORS: details about the update, any description of the update
+#: ../client/pk-console.c:367
 msgid "Update text"
-msgstr "Actualizar detalle"
+msgstr "Texto de actualización"
 
-#: ../client/pk-console.c:354
+#. TRANSLATORS: details about the update, the changelog for the package
+#: ../client/pk-console.c:371
 msgid "Changes"
-msgstr ""
+msgstr "Cambios"
 
-#: ../client/pk-console.c:356
+#. TRANSLATORS: details about the update, the ongoing state of the update
+#: ../client/pk-console.c:375
 msgid "State"
-msgstr ""
+msgstr "Estado"
 
-#: ../client/pk-console.c:359
+#. TRANSLATORS: details about the update, date the update was issued
+#: ../client/pk-console.c:380
 msgid "Issued"
-msgstr ""
+msgstr "Emitido"
 
-#: ../client/pk-console.c:362
-#, fuzzy
+#. TRANSLATORS: details about the update, date the update was updated
+#: ../client/pk-console.c:385
 msgid "Updated"
-msgstr "Actualizar detalle"
+msgstr "Actualizado"
 
-#: ../client/pk-console.c:448 ../client/pk-console.c:450
+#: ../client/pk-console.c:472
+#: ../client/pk-console.c:474
 msgid "Percentage"
-msgstr ""
+msgstr "Porcentaje"
 
-#: ../client/pk-console.c:450
+#: ../client/pk-console.c:474
 msgid "Unknown"
-msgstr ""
+msgstr "Desconocido"
 
 #. TRANSLATORS: a package requires the system to be restarted
-#: ../client/pk-console.c:501
-#, fuzzy
+#: ../client/pk-console.c:525
 msgid "System restart required by:"
-msgstr "Se requiere reiniciar el sistema"
+msgstr "Se necesita reiniciar el sistema debido a:"
 
 #. TRANSLATORS: a package requires the session to be restarted
-#: ../client/pk-console.c:504
-#, fuzzy
+#: ../client/pk-console.c:528
 msgid "Session restart required:"
-msgstr "Se requiere reiniciar el sistema"
+msgstr "Se necesita reiniciar la sesión:"
 
 #. TRANSLATORS: a package requires the application to be restarted
-#: ../client/pk-console.c:507
-#, fuzzy
+#: ../client/pk-console.c:531
 msgid "Application restart required by:"
-msgstr "Se requiere reiniciar una aplicación"
+msgstr "Se necesita reiniciar una aplicación debido a:"
 
-#: ../client/pk-console.c:543
+#. TRANSLATORS: a package needs to restart they system
+#: ../client/pk-console.c:568
 msgid "Please restart the computer to complete the update."
 msgstr "Por favor, reinicie la computadora para completar la actualización"
 
-#: ../client/pk-console.c:545
+#. TRANSLATORS: a package needs to restart the session
+#: ../client/pk-console.c:571
 msgid "Please logout and login to complete the update."
 msgstr "Por favor, salga y vuelva a entrar para completar la actualización."
 
-#: ../client/pk-console.c:547
+#. TRANSLATORS: a package needs to restart the application
+#: ../client/pk-console.c:574
 msgid "Please restart the application as it is being used."
 msgstr "Por favor, reinicie la aplicación que está usando."
 
 #. TRANSLATORS: The package is already installed on the system
-#: ../client/pk-console.c:659
+#: ../client/pk-console.c:687
 #, c-format
 msgid "The package %s is already installed"
 msgstr "El paquete %s ya está instalado"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:667
+#: ../client/pk-console.c:695
 #, c-format
 msgid "The package %s could not be installed: %s"
 msgstr "El paquete %s no se pudo instalar: %s"
 
 #. TRANSLATORS: There was a programming error that shouldn't happen. The detailed error follows
-#: ../client/pk-console.c:692 ../client/pk-console.c:719
-#: ../client/pk-console.c:815 ../client/pk-console.c:932
-#: ../client/pk-tools-common.c:61 ../client/pk-tools-common.c:79
+#: ../client/pk-console.c:720
+#: ../client/pk-console.c:747
+#: ../client/pk-console.c:843
+#: ../client/pk-console.c:960
+#: ../client/pk-tools-common.c:61
+#: ../client/pk-tools-common.c:79
 #: ../client/pk-tools-common.c:86
 #, c-format
 msgid "Internal error: %s"
 msgstr "Error interno: %s"
 
 #. TRANSLATORS: There was an error installing the packages. The detailed error follows
-#: ../client/pk-console.c:700 ../client/pk-console.c:1327
+#: ../client/pk-console.c:728
+#: ../client/pk-console.c:1355
 #, c-format
 msgid "This tool could not install the packages: %s"
 msgstr "Esta herramienta no pudo instalar los paquetes: %s"
 
 #. TRANSLATORS: There was an error installing the files. The detailed error follows
-#: ../client/pk-console.c:727
+#: ../client/pk-console.c:755
 #, c-format
 msgid "This tool could not install the files: %s"
 msgstr "Esta herramienta no pudo instalar los archivos: %s"
 
 #. TRANSLATORS: The package name was not found in the installed list. The detailed error follows
-#: ../client/pk-console.c:783
+#: ../client/pk-console.c:811
 #, c-format
 msgid "This tool could not remove %s: %s"
 msgstr "Esta herramienta no pudo eliminar %s: %s"
 
 #. TRANSLATORS: There was an error removing the packages. The detailed error follows
-#: ../client/pk-console.c:806 ../client/pk-console.c:844
-#: ../client/pk-console.c:877
+#: ../client/pk-console.c:834
+#: ../client/pk-console.c:872
+#: ../client/pk-console.c:905
 #, c-format
 msgid "This tool could not remove the packages: %s"
 msgstr "Esta herramienta no pudo eliminar los paquetes: %s"
 
 #. TRANSLATORS: When removing, we might have to remove other dependencies
-#: ../client/pk-console.c:856
+#: ../client/pk-console.c:884
 msgid "The following packages have to be removed:"
 msgstr "Los siguientes paquetes se eliminarán:"
 
 #. TRANSLATORS: We are checking if it's okay to remove a list of packages
-#: ../client/pk-console.c:863
+#: ../client/pk-console.c:891
 msgid "Proceed removing additional packages?"
 msgstr "¿De acuerdo con eliminar los paquetes adicionales?"
 
 #. TRANSLATORS: We did not remove any packages
-#: ../client/pk-console.c:868
+#: ../client/pk-console.c:896
 msgid "The package removal was canceled!"
 msgstr "¡La eliminación de paquetes fue cancelada!"
 
 #. TRANSLATORS: The package name was not found in any software sources
-#: ../client/pk-console.c:909
+#: ../client/pk-console.c:937
 #, c-format
 msgid "This tool could not download the package %s as it could not be found"
-msgstr ""
-"Esta herramienta no pudo descargar el paquete %s debido a que no fue "
-"encontrado"
+msgstr "Esta herramienta no pudo descargar el paquete %s debido a que no fue encontrado"
 
 #. TRANSLATORS: Could not download the packages for some reason. The detailed error follows
-#: ../client/pk-console.c:940
+#: ../client/pk-console.c:968
 #, c-format
 msgid "This tool could not download the packages: %s"
 msgstr "Esta herramienta no pudo descargar los paquetes: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:967 ../client/pk-console.c:976
+#: ../client/pk-console.c:995
+#: ../client/pk-console.c:1004
 #, c-format
 msgid "This tool could not update %s: %s"
 msgstr "Esta herramienta no pudo actualizar %s: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:998 ../client/pk-console.c:1006
+#: ../client/pk-console.c:1026
+#: ../client/pk-console.c:1034
 #, c-format
 msgid "This tool could not get the requirements for %s: %s"
 msgstr "Esta herramienta no pudo obtener los requerimientos de %s: %s"
 
 #. TRANSLATORS: There was an error getting the dependencies for the package. The detailed error follows
-#: ../client/pk-console.c:1028 ../client/pk-console.c:1036
+#: ../client/pk-console.c:1056
+#: ../client/pk-console.c:1064
 #, c-format
 msgid "This tool could not get the dependencies for %s: %s"
 msgstr "Esta herramienta no pudo obtener las dependencias de %s: %s"
 
 #. TRANSLATORS: There was an error getting the details about the package. The detailed error follows
-#: ../client/pk-console.c:1058 ../client/pk-console.c:1066
+#: ../client/pk-console.c:1086
+#: ../client/pk-console.c:1094
 #, c-format
 msgid "This tool could not get package details for %s: %s"
 msgstr "Esta herramienta no pudo obtener los detalles del paquete %s: %s"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:1088
+#: ../client/pk-console.c:1116
 #, c-format
 msgid "This tool could not find the files for %s: %s"
 msgstr "Esta herramienta no pudo encontrar los archivos de %s: %s"
 
 #. TRANSLATORS: There was an error getting the list of files for the package. The detailed error follows
-#: ../client/pk-console.c:1096
+#: ../client/pk-console.c:1124
 #, c-format
 msgid "This tool could not get the file list for %s: %s"
 msgstr "Esta herramienta no pudo obtener la lista de archivos de %s: %s"
 
 #. TRANSLATORS: There was an error getting the list of packages. The filename follows
-#: ../client/pk-console.c:1118
+#: ../client/pk-console.c:1146
 #, c-format
 msgid "File already exists: %s"
 msgstr "El archivo ya existe: %s"
 
 #. TRANSLATORS: follows a list of packages to install
-#: ../client/pk-console.c:1123 ../client/pk-console.c:1179
-#: ../client/pk-console.c:1254
+#: ../client/pk-console.c:1151
+#: ../client/pk-console.c:1207
+#: ../client/pk-console.c:1282
 msgid "Getting package list"
 msgstr "Obteniendo la lista de paquetes"
 
 #. TRANSLATORS: There was an error getting the list of packages. The detailed error follows
-#: ../client/pk-console.c:1129 ../client/pk-console.c:1185
-#: ../client/pk-console.c:1260
+#: ../client/pk-console.c:1157
+#: ../client/pk-console.c:1213
+#: ../client/pk-console.c:1288
 #, c-format
 msgid "This tool could not get package list: %s"
 msgstr "Esta herramienta no pudo obtener la lista de paquetes: %s"
 
 #. TRANSLATORS: There was an error saving the list
-#: ../client/pk-console.c:1140
-#, c-format
+#: ../client/pk-console.c:1168
 msgid "Failed to save to disk"
 msgstr "Falló al guardar en el disco"
 
 #. TRANSLATORS: There was an error getting the list. The filename follows
-#: ../client/pk-console.c:1174 ../client/pk-console.c:1249
+#: ../client/pk-console.c:1202
+#: ../client/pk-console.c:1277
 #, c-format
 msgid "File does not exist: %s"
 msgstr "El archivo no existe: %s"
 
 #. TRANSLATORS: header to a list of packages newly added
-#: ../client/pk-console.c:1206
+#: ../client/pk-console.c:1234
 msgid "Packages to add"
 msgstr "Paquetes a agregar"
 
 #. TRANSLATORS: header to a list of packages removed
-#: ../client/pk-console.c:1214
+#: ../client/pk-console.c:1242
 msgid "Packages to remove"
 msgstr "Paquetes a eliminar"
 
 #. TRANSLATORS: We didn't find any differences
-#: ../client/pk-console.c:1282
-#, c-format
+#: ../client/pk-console.c:1310
 msgid "No new packages need to be installed"
 msgstr "No hay paquetes nuevos para instalar"
 
 #. TRANSLATORS: follows a list of packages to install
-#: ../client/pk-console.c:1288
+#: ../client/pk-console.c:1316
 msgid "To install"
 msgstr "A instalar"
 
 #. TRANSLATORS: searching takes some time....
-#: ../client/pk-console.c:1299
+#: ../client/pk-console.c:1327
 msgid "Searching for package: "
 msgstr "Buscando el paquete:"
 
 #. TRANSLATORS: package was not found -- this is the end of a string ended in ...
-#: ../client/pk-console.c:1303
+#: ../client/pk-console.c:1331
 msgid "not found."
 msgstr "no encontrado."
 
 #. TRANSLATORS: We didn't find any packages to install
-#: ../client/pk-console.c:1314
-#, c-format
+#: ../client/pk-console.c:1342
 msgid "No packages can be found to install"
 msgstr "No se encontró ningún paquete para instalar"
 
 #. TRANSLATORS: installing new packages from package list
-#: ../client/pk-console.c:1320
+#: ../client/pk-console.c:1348
 msgid "Installing packages"
 msgstr "Instalando paquetes"
 
 #. TRANSLATORS: The package name was not found in any software sources. The detailed error follows
-#: ../client/pk-console.c:1356
+#: ../client/pk-console.c:1384
 #, c-format
 msgid "This tool could not find the update details for %s: %s"
-msgstr ""
-"Esta herramienta no pudo encontrar los detalles de actualización de %s: %s"
+msgstr "Esta herramienta no pudo encontrar los detalles de actualización de %s: %s"
 
 #. TRANSLATORS: There was an error getting the details about the update for the package. The detailed error follows
-#: ../client/pk-console.c:1364
+#: ../client/pk-console.c:1392
 #, c-format
 msgid "This tool could not get the update details for %s: %s"
-msgstr ""
-"Esta herramienta no pudo obtener los detalles de actualización de %s: %s"
+msgstr "Esta herramienta no pudo obtener los detalles de actualización de %s: %s"
 
 #. TRANSLATORS: This was an unhandled error, and we don't have _any_ context
-#: ../client/pk-console.c:1410
+#: ../client/pk-console.c:1438
 msgid "Error:"
 msgstr "Error:"
 
 #. TRANSLATORS: This a list of details about the package
-#: ../client/pk-console.c:1424
+#: ../client/pk-console.c:1452
 msgid "Package description"
 msgstr "Descripción del paquete"
 
 #. TRANSLATORS: This a list files contained in the package
-#: ../client/pk-console.c:1458
+#: ../client/pk-console.c:1486
 msgid "Package files"
 msgstr "Archivos del paquete"
 
 #. TRANSLATORS: This where the package has no files
-#: ../client/pk-console.c:1466
+#: ../client/pk-console.c:1494
 msgid "No files"
 msgstr "No hay archivos"
 
 #. TRANSLATORS: This a request for a GPG key signature from the backend, which the client will prompt for later
-#: ../client/pk-console.c:1489
+#: ../client/pk-console.c:1517
 msgid "Repository signature required"
 msgstr "Se requiere la firma del repositorio"
 
 #. TRANSLATORS: This a prompt asking the user to import the security key
-#: ../client/pk-console.c:1499
+#: ../client/pk-console.c:1527
 msgid "Do you accept this signature?"
 msgstr "¿Acepta esta firma?"
 
 #. TRANSLATORS: This is where the user declined the security key
-#: ../client/pk-console.c:1503
+#: ../client/pk-console.c:1531
 msgid "The signature was not accepted."
 msgstr "La firma no fue aceptada."
 
 #. TRANSLATORS: This a request for a EULA
-#: ../client/pk-console.c:1537
+#: ../client/pk-console.c:1565
 msgid "End user license agreement required"
 msgstr "Se requiere un acuerdo de licencia de usuario final"
 
 #. TRANSLATORS: This a prompt asking the user to agree to the license
-#: ../client/pk-console.c:1544
+#: ../client/pk-console.c:1572
 msgid "Do you agree to this license?"
 msgstr "¿Está de acuerdo con esta licencia?"
 
 #. TRANSLATORS: This is where the user declined the license
-#: ../client/pk-console.c:1548
+#: ../client/pk-console.c:1576
 msgid "The license was refused."
 msgstr "La licencia fue rechazada."
 
 #. TRANSLATORS: This is when the daemon crashed, and we are up shit creek without a paddle
-#: ../client/pk-console.c:1577
+#: ../client/pk-console.c:1605
 msgid "The daemon crashed mid-transaction!"
 msgstr "El servicio terminó en medio de una transacción!"
 
 #. TRANSLATORS: This is the header to the --help menu
-#: ../client/pk-console.c:1630
+#: ../client/pk-console.c:1658
 msgid "PackageKit Console Interface"
 msgstr "Interfaz de Consola de PackageKit"
 
-#: ../client/pk-console.c:1630
+#. these are commands we can use with pkcon
+#: ../client/pk-console.c:1660
 msgid "Subcommands:"
 msgstr "Subcomandos:"
 
-#: ../client/pk-console.c:1719 ../client/pk-generate-pack.c:184
-#: ../client/pk-monitor.c:115
+#. TRANSLATORS: command line argument, if we should show debugging information
+#. TRANSLATORS: if we should show debugging data
+#: ../client/pk-console.c:1752
+#: ../client/pk-generate-pack.c:185
+#: ../client/pk-monitor.c:125
 #: ../contrib/command-not-found/pk-command-not-found.c:510
-#: ../src/pk-main.c:192
+#: ../src/pk-main.c:199
 msgid "Show extra debugging information"
 msgstr "Mostrar información extra de depuración"
 
-#: ../client/pk-console.c:1721 ../client/pk-monitor.c:117
+#. TRANSLATORS: command line argument, just show the version string
+#: ../client/pk-console.c:1755
+#: ../client/pk-monitor.c:127
 msgid "Show the program version and exit"
 msgstr "Mostrar la versión del programa y salir"
 
-#: ../client/pk-console.c:1723
+#. TRANSLATORS: command line argument, use a filter to narrow down results
+#: ../client/pk-console.c:1758
 msgid "Set the filter, e.g. installed"
 msgstr "Defina el filtro, ej. installado"
 
-#: ../client/pk-console.c:1725
+#. TRANSLATORS: command line argument, work asynchronously
+#: ../client/pk-console.c:1761
 msgid "Exit without waiting for actions to complete"
 msgstr "Salir sin esperar que las acciones se completen"
 
 #. TRANSLATORS: This is when we could not connect to the system bus, and is fatal
-#: ../client/pk-console.c:1752
+#: ../client/pk-console.c:1788
 msgid "This tool could not connect to system DBUS."
 msgstr "Esta herramienta no se pudo conectar al DBUS del sistema."
 
 #. TRANSLATORS: The user specified an incorrect filter
-#: ../client/pk-console.c:1839
+#: ../client/pk-console.c:1875
 msgid "The filter specified was invalid"
 msgstr "El filtro especificado fue inválido"
 
-#: ../client/pk-console.c:1856
-msgid "You need to specify a search type, e.g. name"
-msgstr "Debe especificar el tipo de búsqueda, por ejemplo, nombre"
+#. TRANSLATORS: a search type can be name, details, file, etc
+#: ../client/pk-console.c:1893
+msgid "A search type is required, e.g. name"
+msgstr "Se necesita un tipo de búsqueda, por ejemplo, nombre"
 
-#: ../client/pk-console.c:1861 ../client/pk-console.c:1868
-#: ../client/pk-console.c:1875 ../client/pk-console.c:1882
-#: ../client/pk-console.c:1990 ../client/pk-console.c:2000
-#: ../client/pk-console.c:2007 ../client/pk-console.c:2014
-msgid "You need to specify a search term"
-msgstr "Debe especificar un término de búsqueda"
+#. TRANSLATORS: the user needs to provide a search term
+#: ../client/pk-console.c:1899
+#: ../client/pk-console.c:1907
+#: ../client/pk-console.c:1915
+#: ../client/pk-console.c:1923
+msgid "A search term is required"
+msgstr "Se necesita un término de búsqueda"
 
-#: ../client/pk-console.c:1887
+#. TRANSLATORS: the search type was provided, but invalid
+#: ../client/pk-console.c:1929
 msgid "Invalid search type"
 msgstr "Tipo de búsqueda inválido"
 
-#: ../client/pk-console.c:1892
-msgid "You need to specify a package or file to install"
-msgstr "Debe especificar un paquete o archivo a instalar"
+#. TRANSLATORS: the user did not specify what they wanted to install
+#: ../client/pk-console.c:1935
+msgid "A package name or filename to install is required"
+msgstr "Se requiere un nombre de paquete o nombre de archivo a instalar"
 
-#: ../client/pk-console.c:1899
-msgid "You need to specify a type, key_id and package_id"
-msgstr "Debe especificar un tipo, key_id y package_id"
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1943
+msgid "A type, key_id and package_id are required"
+msgstr "Se necesita un tipo, key_id y package_id"
 
-#: ../client/pk-console.c:1906
-msgid "You need to specify a package to remove"
-msgstr "Debe especificar un paquete a eliminar"
+#. TRANSLATORS: the user did not specify what they wanted to remove
+#: ../client/pk-console.c:1951
+msgid "A package name to remove is required"
+msgstr "Necesita dar un nombre de paquete a eliminar"
 
-#: ../client/pk-console.c:1912
-msgid ""
-"You need to specify the destination directory and then the packages to "
-"download"
-msgstr ""
-"Debe especificar el directorio destino y luego los paquetes a descargar"
+#. TRANSLATORS: the user did not specify anything about what to download or where
+#: ../client/pk-console.c:1958
+msgid "A destination directory and then the package names to download are required"
+msgstr "Debe especificar el directorio destino y luego los nombres paquetes a descargar"
 
-#: ../client/pk-console.c:1917
+#. TRANSLATORS: the directory does not exist, so we can't continue
+#: ../client/pk-console.c:1964
 msgid "Directory not found"
 msgstr "Directorio no encontrado"
 
-#: ../client/pk-console.c:1923
-msgid "You need to specify a licence identifier (eula-id)"
-msgstr "Debe especificar un identificador de licencia (eula-id)"
-
-#: ../client/pk-console.c:1939
-msgid "You need to specify a package name to resolve"
-msgstr "Debe especificar un nombre de paquete a resolver"
-
-#: ../client/pk-console.c:1946 ../client/pk-console.c:1953
-msgid "You need to specify a repository name"
-msgstr "Debe especificar un nombre de repositorio"
-
-#: ../client/pk-console.c:1960
-msgid "You need to specify a repo name/parameter and value"
-msgstr "Debe especificar un nombre/parametro de repositorio y valor"
-
-#: ../client/pk-console.c:1972
-msgid "You need to specify an action, e.g. 'update-system'"
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1971
+msgid "A licence identifier (eula-id) is required"
+msgstr "Se necesita un identificador de licencia (eula-id)"
+
+#. TRANSLATORS: geeky error, 99.9999% of users won't see this
+#: ../client/pk-console.c:1980
+msgid "A transaction identifier (tid) is required"
+msgstr "Se necesita un identificador de transacción (tid)"
+
+#. TRANSLATORS: The user did not specify a package name
+#: ../client/pk-console.c:1996
+msgid "A package name to resolve is required"
+msgstr "Se necesita un nombre de paquete a resolver"
+
+#. TRANSLATORS: The user did not specify a repository (software source) name
+#: ../client/pk-console.c:2004
+#: ../client/pk-console.c:2012
+msgid "A repository name is required"
+msgstr "Se necesita un nombre de repositorio"
+
+#. TRANSLATORS: The user didn't provide any data
+#: ../client/pk-console.c:2020
+msgid "A repo name, parameter and value are required"
+msgstr "Debe especificar un nombre de repositorio, parametro y valor"
+
+#. TRANSLATORS: The user didn't specify what action to use
+#: ../client/pk-console.c:2033
+msgid "An action, e.g. 'update-system' is required"
 msgstr "Debe especificar una acción, por ejemplo, 'update-system'"
 
-#: ../client/pk-console.c:1977
-msgid "You need to specify a correct role"
-msgstr "Debe especificar un rol correcto"
-
-#: ../client/pk-console.c:1982
-msgid "Failed to get last time"
-msgstr "Fállo al obtener última hora"
-
-#: ../client/pk-console.c:2021
-msgid "You need to specify a package to find the details for"
-msgstr "Debe especificar un paquete para el que buscar la descripción"
-
-#: ../client/pk-console.c:2028
-msgid "You need to specify a package to find the files for"
-msgstr "Debe especificar un paquete para el que buscar los archivos"
-
-#: ../client/pk-console.c:2035
-msgid "You need to specify a list file to create"
-msgstr "Debe especificar un archivo de lista a crear"
-
-#: ../client/pk-console.c:2043 ../client/pk-console.c:2051
-msgid "You need to specify a list file to open"
-msgstr "Debe especificar un archivo de lista a abrir"
+#. TRANSLATORS: The user specified an invalid action
+#: ../client/pk-console.c:2039
+msgid "A correct role is required"
+msgstr "Se necesita el rol correcto"
+
+#. TRANSLATORS: we keep a database updated with the time that an action was last executed
+#: ../client/pk-console.c:2045
+msgid "Failed to get the time since this action was last completed"
+msgstr "Falló al obtener la hora de la última vez que se completó esta acción"
+
+#. TRANSLATORS: The user did not provide a package name
+#. TRANSLATORS: This is when the user fails to supply the package name
+#: ../client/pk-console.c:2054
+#: ../client/pk-console.c:2065
+#: ../client/pk-console.c:2073
+#: ../client/pk-console.c:2089
+#: ../client/pk-console.c:2097
+#: ../client/pk-generate-pack.c:241
+msgid "A package name is required"
+msgstr "Se necesita un nombre de paquete"
+
+#. TRANSLATORS: each package "provides" certain things, e.g. mime(gstreamer-decoder-mp3), the user didn't specify it
+#: ../client/pk-console.c:2081
+msgid "A package provide string is required"
+msgstr "Se necesita la cadena de lo que provee el paquete"
+
+#. TRANSLATORS: The user didn't specify a filename to create as a list
+#: ../client/pk-console.c:2105
+msgid "A list file name to create is required"
+msgstr "Se necesita un nombre de archivo de la lista"
+
+#. TRANSLATORS: The user didn't specify a filename to open as a list
+#: ../client/pk-console.c:2114
+#: ../client/pk-console.c:2123
+msgid "A list file to open is required"
+msgstr "Se necesita un archivo de lista a abrir"
 
 #. TRANSLATORS: The user tried to use an unsupported option on the command line
-#: ../client/pk-console.c:2104
+#: ../client/pk-console.c:2176
 #, c-format
 msgid "Option '%s' is not supported"
 msgstr "La opción '%s' no está soportada"
 
 #. TRANSLATORS: User does not have permission to do this
-#: ../client/pk-console.c:2117
-msgid "You don't have the necessary privileges for this operation"
-msgstr "No tiene los privilegios necesarios para esta operación"
+#: ../client/pk-console.c:2189
+msgid "Incorrect privileges for this operation"
+msgstr "Privilegios incorrectos para esta operación"
 
 #. TRANSLATORS: Generic failure of what they asked to do
-#: ../client/pk-console.c:2120
+#: ../client/pk-console.c:2192
 msgid "Command failed"
 msgstr "Commando falló"
 
 #. TRANSLATORS: This is the state of the transaction
-#: ../client/pk-generate-pack.c:100
+#: ../client/pk-generate-pack.c:101
 msgid "Downloading"
 msgstr "Descargando"
 
 #. TRANSLATORS: This is when the main packages are being downloaded
-#: ../client/pk-generate-pack.c:120
+#: ../client/pk-generate-pack.c:121
 msgid "Downloading packages"
 msgstr "Descargando paquetes"
 
 #. TRANSLATORS: This is when the dependency packages are being downloaded
-#: ../client/pk-generate-pack.c:125
+#: ../client/pk-generate-pack.c:126
 msgid "Downloading dependencies"
 msgstr "Descargando dependencias"
 
-#: ../client/pk-generate-pack.c:186
+#. TRANSLATORS: we can exclude certain packages (glibc) when we know they'll exist on the target
+#: ../client/pk-generate-pack.c:188
 msgid "Set the file name of dependencies to be excluded"
 msgstr "Ponga el nombre del archivo de dependencias a excluir"
 
-#: ../client/pk-generate-pack.c:188
-msgid "The output directory (the current directory is used if ommitted)"
-msgstr "El directorio de salida (el directorio actual se usará si se omite)"
+#. TRANSLATORS: the output location
+#: ../client/pk-generate-pack.c:191
+msgid "The output file or directory (the current directory is used if ommitted)"
+msgstr "El directorio o archivo de salida (el directorio actual se usará si se omite)"
 
-#: ../client/pk-generate-pack.c:190
+#. TRANSLATORS: put a list of packages in the pack
+#: ../client/pk-generate-pack.c:194
 msgid "The package to be put into the service pack"
 msgstr "El paquete será puesto en el paquete de servicio"
 
-#: ../client/pk-generate-pack.c:192
+#. TRANSLATORS: put all pending updates in the pack
+#: ../client/pk-generate-pack.c:197
 msgid "Put all updates available in the service pack"
 msgstr "Poner todas las actualizaciones disponibles en el paquete de servicio"
 
 #. TRANSLATORS: This is when the user fails to supply the correct arguments
-#: ../client/pk-generate-pack.c:220
+#: ../client/pk-generate-pack.c:225
 msgid "Neither --package or --updates option selected."
 msgstr "No se seleccionó ni la opción --package o --updates."
 
 #. TRANSLATORS: This is when the user fails to supply just one argument
-#: ../client/pk-generate-pack.c:228
+#: ../client/pk-generate-pack.c:233
 msgid "Both options selected."
 msgstr "Se seleccionaron ambas opciones."
 
+#. TRANSLATORS: This is when the user fails to supply the output
+#: ../client/pk-generate-pack.c:249
+msgid "A output directory or file name is required"
+msgstr "Se necesita un directorio o nombre de archivo de salida"
+
+#. TRANSLATORS: This is when the backend doesn't have the capability to get-depends
+#. TRANSLATORS: This is when the backend doesn't have the capability to download
+#: ../client/pk-generate-pack.c:267
+#: ../client/pk-generate-pack.c:273
+msgid "The package manager cannot perform this type of operation."
+msgstr "El administrador de paquetes no puede realizar este tipo de operación."
+
+#. TRANSLATORS: the user specified an absolute path, but didn't get the extension correct
+#: ../client/pk-generate-pack.c:285
+msgid "If specifying a file, the service pack name must end with"
+msgstr "Si especifica un archivo, el nombre del paquete de servicio debe finalizar con"
+
 #. TRANSLATORS: This is when file already exists
-#: ../client/pk-generate-pack.c:261
+#: ../client/pk-generate-pack.c:301
 msgid "A pack with the same name already exists, do you want to overwrite it?"
 msgstr "Ya existe un paquete con ese nombre, ¿desea sobreescribirlo ?"
 
 #. TRANSLATORS: This is when the pack was not overwritten
-#: ../client/pk-generate-pack.c:264
+#: ../client/pk-generate-pack.c:304
 msgid "The pack was not overwritten."
 msgstr "El paquete no fue sobrescrito."
 
 #. TRANSLATORS: This is when the temporary directory cannot be created, the directory name follows
-#: ../client/pk-generate-pack.c:276
+#: ../client/pk-generate-pack.c:317
 msgid "Failed to create directory:"
 msgstr "No se pudo crear el directorio:"
 
 #. TRANSLATORS: This is when the list of packages from the remote computer cannot be opened
-#: ../client/pk-generate-pack.c:285
+#: ../client/pk-generate-pack.c:327
 msgid "Failed to open package list."
 msgstr "Falló al abrir la lista de paquetes."
 
 #. TRANSLATORS: The package name is being matched up to available packages
-#: ../client/pk-generate-pack.c:295
+#: ../client/pk-generate-pack.c:338
 msgid "Finding package name."
 msgstr "Buscando el nombre de paquete."
 
 #. TRANSLATORS: This is when the package cannot be found in any software source. The detailed error follows
-#: ../client/pk-generate-pack.c:299
+#: ../client/pk-generate-pack.c:342
 #, c-format
 msgid "Failed to find package '%s': %s"
 msgstr "Falló al buscar el paquete '%s': %s"
 
 #. TRANSLATORS: This is telling the user we are in the process of making the pack
-#: ../client/pk-generate-pack.c:315
+#: ../client/pk-generate-pack.c:359
 msgid "Creating service pack..."
 msgstr "Creando el paquete de servicios..."
 
 #. TRANSLATORS: we succeeded in making the file
-#: ../client/pk-generate-pack.c:322
+#: ../client/pk-generate-pack.c:366
 #, c-format
 msgid "Service pack created '%s'"
 msgstr "El paqute de servicio '%s' fue creado"
 
 #. TRANSLATORS: we failed to make te file
-#: ../client/pk-generate-pack.c:326
+#: ../client/pk-generate-pack.c:371
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Falló al crear '%s': %s"
 
-#: ../client/pk-monitor.c:132
+#. TRANSLATORS: this is a program that monitors PackageKit
+#: ../client/pk-monitor.c:143
 msgid "PackageKit Monitor"
 msgstr "Monitor de PackageKit"
 
 #. TRANSLATORS: The package was not found in any software sources
 #: ../client/pk-tools-common.c:114
-#, c-format
 msgid "The package could not be found"
 msgstr "No se pudo encontrar el paquete"
 
@@ -724,80 +798,72 @@ msgstr "Por favor ingrese un número de 1 a %i:"
 
 #. TRANSLATORS: we failed to find the package, this shouldn't happen
 #: ../contrib/command-not-found/pk-command-not-found.c:361
-#, fuzzy
 msgid "Failed to search for file"
-msgstr "Falló al guardar en el disco"
+msgstr "Falló al buscar el archivo"
 
 #. TRANSLATORS: we failed to launch the executable, the error follows
 #: ../contrib/command-not-found/pk-command-not-found.c:485
-#, fuzzy
 msgid "Failed to launch:"
-msgstr "Fállo al obtener última hora"
+msgstr "Fállo al iniciar:"
 
 #. TRANSLATORS: tool that gets called when the command is not found
 #: ../contrib/command-not-found/pk-command-not-found.c:526
-#, fuzzy
 msgid "PackageKit Command Not Found"
-msgstr "Monitor de PackageKit"
+msgstr "Comando PackageKit no encontrado"
 
 #. TRANSLATORS: the prefix of all the output telling the user why it's not executing
 #: ../contrib/command-not-found/pk-command-not-found.c:548
-#, fuzzy
 msgid "Command not found."
-msgstr "no encontrado."
+msgstr "Comando no encontrado."
 
 #. TRANSLATORS: tell the user what we think the command is
 #: ../contrib/command-not-found/pk-command-not-found.c:555
-#, fuzzy
 msgid "Similar command is:"
-msgstr "Subcomandos:"
+msgstr "Un comando similar es:"
 
 #. TRANSLATORS: Ask the user if we should run the similar command
 #: ../contrib/command-not-found/pk-command-not-found.c:564
 msgid "Run similar command:"
-msgstr ""
+msgstr "Ejecutar un comando similar:"
 
 #. TRANSLATORS: show the user a list of commands that they could have meant
 #. TRANSLATORS: show the user a list of commands we could run
 #: ../contrib/command-not-found/pk-command-not-found.c:576
 #: ../contrib/command-not-found/pk-command-not-found.c:585
-#, fuzzy
 msgid "Similar commands are:"
-msgstr "Subcomandos:"
+msgstr "Los comandos similares son:"
 
 #. TRANSLATORS: ask the user to choose a file to run
 #: ../contrib/command-not-found/pk-command-not-found.c:592
 msgid "Please choose a command to run"
-msgstr ""
+msgstr "Por favor, elija un comando a ejecutar"
 
 #. TRANSLATORS: tell the user what package provides the command
 #: ../contrib/command-not-found/pk-command-not-found.c:607
-#, fuzzy
 msgid "The package providing this file is:"
-msgstr "El paquete %s ya está instalado"
+msgstr "El paquete que provee este archivo es:"
 
 #. TRANSLATORS: as the user if we want to install a package to provide the command
 #: ../contrib/command-not-found/pk-command-not-found.c:612
 #, c-format
 msgid "Install package '%s' to provide command '%s'?"
-msgstr ""
+msgstr "Instalar el paquete '%s' para proveer el comando '%s'?"
 
 #. TRANSLATORS: Show the user a list of packages that provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:633
 msgid "Packages providing this file are:"
-msgstr ""
+msgstr "Los paquetes que proveen este archivo son:"
 
 #. TRANSLATORS: Show the user a list of packages that they can install to provide this command
 #: ../contrib/command-not-found/pk-command-not-found.c:642
 msgid "Suitable packages are:"
-msgstr ""
+msgstr "Los paquetes posibles son:"
 
 #. get selection
 #. TRANSLATORS: ask the user to choose a file to install
 #: ../contrib/command-not-found/pk-command-not-found.c:650
-#, fuzzy
 msgid "Please choose a package to install"
-msgstr "No se pudo encontrar un paquete para instalar"
+msgstr "Por favor, elija un paquete a instalar"
 
 #. TRANSLATORS: when we are getting data from the daemon
 #: ../contrib/browser-plugin/src/contents.cpp:298
@@ -821,6 +887,7 @@ msgstr "Versión instalada"
 msgid "Run version %s now"
 msgstr "Correr la versión %s ahora"
 
+#. TRANSLATORS: run the application now
 #: ../contrib/browser-plugin/src/contents.cpp:324
 msgid "Run now"
 msgstr "Correr ahora"
@@ -864,307 +931,260 @@ msgstr "Lista de Paquetes de PackageKit"
 msgid "PackageKit Service Pack"
 msgstr "Grupo de Servicio de PackageKit"
 
-#: ../policy/org.freedesktop.packagekit.policy.in.h:1
-msgid "Accept EULA"
-msgstr "Aceptar EULA"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:2
-msgid "Authentication is required to accept a EULA"
-msgstr "Se requiere autenticación para aceptar una EULA"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:3
-#, fuzzy
-msgid ""
-"Authentication is required to cancel a task that was not started by yourself"
-msgstr ""
-"Se requiere autenticación para cambiar los parametros de fuente de software"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:4
-msgid "Authentication is required to change software source parameters"
-msgstr ""
-"Se requiere autenticación para cambiar los parametros de fuente de software"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:5
-#, fuzzy
-msgid ""
-"Authentication is required to consider a key used for signing packages as "
-"trusted"
-msgstr "Se requiere autenticación para refrescar la lista de paquetes"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:6
-#, fuzzy
-msgid "Authentication is required to install a signed package"
-msgstr "Se requiere autenticación para instalar un paquete"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:7
-#, fuzzy
-msgid "Authentication is required to install an untrusted package"
-msgstr "Se requiere autenticación para instalar un paquete"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:8
-#, fuzzy
-msgid "Authentication is required to refresh the system sources"
-msgstr "Se requiere autenticación para refrescar la lista de paquetes"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:9
-msgid "Authentication is required to remove packages"
-msgstr "Se requiere autenticación para eliminar paquetes"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:10
-msgid "Authentication is required to rollback a transaction"
-msgstr "Se requiere autenticación para deshacer una transaccion"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:11
-#, fuzzy
-msgid ""
-"Authentication is required to set the network proxy used for downloading "
-"packages"
-msgstr "Se requiere autenticación para eliminar paquetes"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:12
-msgid "Authentication is required to update packages"
-msgstr "Se requiere autenticación para actualizar paquetes"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:13
-msgid "Cancel foreign task"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:14
-msgid "Change software source parameters"
-msgstr "Cambiar los parametros de fuente de software"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:15
-#, fuzzy
-msgid "Install signed package"
-msgstr "Instalando paquetes"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:16
-#, fuzzy
-msgid "Install untrusted local file"
-msgstr "Instalar archivo local"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:17
-msgid "Refresh system sources"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:18
-msgid "Remove package"
-msgstr "Eliminar paquete"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:19
-msgid "Rollback to a previous transaction"
-msgstr "Deshacer hasta una transaccion previa"
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:20
-msgid "Set network proxy"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:21
-msgid "Trust a key used for signing packages"
-msgstr ""
-
-#: ../policy/org.freedesktop.packagekit.policy.in.h:22
-#, fuzzy
-msgid "Update packages"
-msgstr "Actualizar paquete"
-
-#: ../src/pk-main.c:86
+#. TRANSLATORS: failed due to DBus security
+#: ../src/pk-main.c:87
 msgid "Startup failed due to security policies on this machine."
 msgstr "El arranque falló debito a políticas de seguridad en esta máquina."
 
-#: ../src/pk-main.c:87
+#. TRANSLATORS: only two ways this can fail...
+#: ../src/pk-main.c:89
 msgid "This can happen for two reasons:"
 msgstr "Esto puede pasar por dos razones:"
 
-#: ../src/pk-main.c:88
+#. TRANSLATORS: only allowed to be owned by root
+#: ../src/pk-main.c:91
 msgid "The correct user is not launching the executable (usually root)"
 msgstr "El usuario correcto no esta lanzando el ejecutable (usualmente root)"
 
-#: ../src/pk-main.c:89
-msgid ""
-"The org.freedesktop.PackageKit.conf file is not installed in the system "
-"directory:"
-msgstr ""
-"El archivo org.freedesktop.PackageKit.conf no está instalado en el "
-"directorio del sistema:"
+#. TRANSLATORS: or we are installed in a prefix
+#: ../src/pk-main.c:93
+msgid "The org.freedesktop.PackageKit.conf file is not installed in the system directory:"
+msgstr "El archivo org.freedesktop.PackageKit.conf no está instalado en el directorio del sistema:"
 
-#: ../src/pk-main.c:188
+#. TRANSLATORS: a backend is the system package tool, e.g. yum, apt
+#: ../src/pk-main.c:193
 msgid "Packaging backend to use, e.g. dummy"
 msgstr "Administrador de paquetes a usar, ej. dummy"
 
-#: ../src/pk-main.c:190
+#. TRANSLATORS: if we should run in the background
+#: ../src/pk-main.c:196
 msgid "Daemonize and detach from the terminal"
 msgstr "Demonizar y desadjuntar de la terminal"
 
-#: ../src/pk-main.c:194
+#. TRANSLATORS: if we should not monitor how long we are inactive for
+#: ../src/pk-main.c:202
 msgid "Disable the idle timer"
 msgstr "Deshabilitar el idle timer"
 
-#: ../src/pk-main.c:196
+#. TRANSLATORS: show version
+#: ../src/pk-main.c:205
 msgid "Show version and exit"
 msgstr "Mostrar version y salir"
 
-#: ../src/pk-main.c:198
+#. TRANSLATORS: exit after we've started up, used for user profiling
+#: ../src/pk-main.c:208
 msgid "Exit after a small delay"
 msgstr "Salir luego de una pequeña pausa"
 
-#: ../src/pk-main.c:200
+#. TRANSLATORS: exit straight away, used for automatic profiling
+#: ../src/pk-main.c:211
 msgid "Exit after the engine has loaded"
 msgstr "Salir luego de que el motor este cargado"
 
-#: ../src/pk-main.c:214
+#. TRANSLATORS: describing the service that is running
+#: ../src/pk-main.c:226
 msgid "PackageKit service"
 msgstr "Servicio PackageKit"
 
-#: ../src/pk-main.c:250
+#. TRANSLATORS: fatal error, dbus is not running
+#: ../src/pk-main.c:263
 msgid "Cannot connect to the system bus"
 msgstr "No se pudo conectar al bus del sistema"
 
-#: ../src/pk-main.c:299
+#. TRANSLATORS: cannot register on system bus, unknown reason
+#: ../src/pk-main.c:313
 #, c-format
 msgid "Error trying to start: %s\n"
 msgstr "Error intentando arrancar: %s\n"
 
+#~ msgid "You need to specify a search type, e.g. name"
+#~ msgstr "Debe especificar el tipo de búsqueda, por ejemplo, nombre"
+#~ msgid "You need to specify a search term"
+#~ msgstr "Debe especificar un término de búsqueda"
+#~ msgid "You need to specify a package or file to install"
+#~ msgstr "Debe especificar un paquete o archivo a instalar"
+#~ msgid "You need to specify a package to remove"
+#~ msgstr "Debe especificar un paquete a eliminar"
+#~ msgid "You need to specify a package name to resolve"
+#~ msgstr "Debe especificar un nombre de paquete a resolver"
+#~ msgid "You need to specify a repository name"
+#~ msgstr "Debe especificar un nombre de repositorio"
+#~ msgid "You need to specify a correct role"
+#~ msgstr "Debe especificar un rol correcto"
+#~ msgid "Failed to get last time"
+#~ msgstr "Fállo al obtener última hora"
+#~ msgid "You need to specify a package to find the details for"
+#~ msgstr "Debe especificar un paquete para el que buscar la descripción"
+#~ msgid "You need to specify a package to find the files for"
+#~ msgstr "Debe especificar un paquete para el que buscar los archivos"
+#~ msgid "You need to specify a list file to create"
+#~ msgstr "Debe especificar un archivo de lista a crear"
+#~ msgid "You need to specify a list file to open"
+#~ msgstr "Debe especificar un archivo de lista a abrir"
+#~ msgid "Accept EULA"
+#~ msgstr "Aceptar EULA"
+#~ msgid "Authentication is required to accept a EULA"
+#~ msgstr "Se requiere autenticación para aceptar una EULA"
+
+#, fuzzy
+#~ msgid ""
+#~ "Authentication is required to cancel a task that was not started by "
+#~ "yourself"
+#~ msgstr ""
+#~ "Se requiere autenticación para cambiar los parametros de fuente de "
+#~ "software"
+#~ msgid "Authentication is required to change software source parameters"
+#~ msgstr ""
+#~ "Se requiere autenticación para cambiar los parametros de fuente de "
+#~ "software"
+
+#, fuzzy
+#~ msgid ""
+#~ "Authentication is required to consider a key used for signing packages as "
+#~ "trusted"
+#~ msgstr "Se requiere autenticación para refrescar la lista de paquetes"
+
+#, fuzzy
+#~ msgid "Authentication is required to install a signed package"
+#~ msgstr "Se requiere autenticación para instalar un paquete"
+
+#, fuzzy
+#~ msgid "Authentication is required to install an untrusted package"
+#~ msgstr "Se requiere autenticación para instalar un paquete"
+
+#, fuzzy
+#~ msgid "Authentication is required to refresh the system sources"
+#~ msgstr "Se requiere autenticación para refrescar la lista de paquetes"
+#~ msgid "Authentication is required to remove packages"
+#~ msgstr "Se requiere autenticación para eliminar paquetes"
+#~ msgid "Authentication is required to rollback a transaction"
+#~ msgstr "Se requiere autenticación para deshacer una transaccion"
+
+#, fuzzy
+#~ msgid ""
+#~ "Authentication is required to set the network proxy used for downloading "
+#~ "packages"
+#~ msgstr "Se requiere autenticación para eliminar paquetes"
+#~ msgid "Authentication is required to update packages"
+#~ msgstr "Se requiere autenticación para actualizar paquetes"
+#~ msgid "Change software source parameters"
+#~ msgstr "Cambiar los parametros de fuente de software"
+
+#, fuzzy
+#~ msgid "Install signed package"
+#~ msgstr "Instalando paquetes"
+
+#, fuzzy
+#~ msgid "Install untrusted local file"
+#~ msgstr "Instalar archivo local"
+#~ msgid "Remove package"
+#~ msgstr "Eliminar paquete"
+#~ msgid "Rollback to a previous transaction"
+#~ msgstr "Deshacer hasta una transaccion previa"
+
+#, fuzzy
+#~ msgid "Update packages"
+#~ msgstr "Actualizar paquete"
 #~ msgid "This tool could not remove the packages: '%s'"
 #~ msgstr "Esta herramienta no pudo eliminar los paquetes: '%s'"
-
 #~ msgid "Install local file"
 #~ msgstr "Instalar archivo local"
-
 #~ msgid "Okay to import key?"
 #~ msgstr "¿De acuerto con importer la clave?"
-
 #~ msgid "Did not import key"
 #~ msgstr "No se importó la clave"
-
 #~ msgid "Do you agree?"
 #~ msgstr "¿Está de acuerdo?"
-
-#~ msgid "A logout and login is required"
-#~ msgstr "Se requiere reiniciar la sesión"
-
 #~ msgid "Could not find package to remove"
 #~ msgstr "No se pudo encontrar el paquete a eliminar"
-
 #~ msgid "Cancelled!"
 #~ msgstr "Cancelado!"
-
 #~ msgid "Could not find package to update"
 #~ msgstr "No se pudo encontrar el paquete a actualizar"
-
 #~ msgid "Could not find what packages require"
 #~ msgstr "No se pudo encontrar cuales paquetes requiere este paquete"
-
 #~ msgid "Could not find details for"
 #~ msgstr "No se pudieron obtener los detalles de "
-
 #~ msgid "Could not find a package match"
 #~ msgstr "No se pudo encontrar un paquete coincidente"
 
 #, fuzzy
-#~ msgid "Resolving package name to remote object"
-#~ msgstr "Los siguientes paquetes deben ser removidos"
-
-#, fuzzy
 #~ msgid "Could not set database readonly"
 #~ msgstr "No se pudo abrir la base de datos: %s"
-
 #~ msgid "Could not open database: %s"
 #~ msgstr "No se pudo abrir la base de datos: %s"
-
 #~ msgid "You probably need to run this program as the root user"
 #~ msgstr "Probablemente necesita ejecutar este programa como el usuario root"
-
 #~ msgid "<span color='#%06x' underline='single' size='larger'>Run %s</span>"
 #~ msgstr ""
 #~ "<span color='#%06x' underline='single' size='larger'>Ejecutar %s</span>"
-
 #~ msgid "<big>%s</big>"
 #~ msgstr "<big>%s</big>"
-
 #~ msgid ""
 #~ "\n"
 #~ "<span color='#%06x' underline='single'>Run version %s now</span>"
 #~ msgstr ""
 #~ "\n"
 #~ "<span color='#%06x' underline='single'>Ejecutar versión %s ahora</span>"
-
 #~ msgid ""
 #~ "\n"
 #~ "<span color='#%06x' underline='single'>Run now</span>"
 #~ msgstr ""
 #~ "\n"
 #~ "<span color='#%06x' underline='single'>Ejecutar ahora</span>"
-
 #~ msgid ""
 #~ "\n"
 #~ "<span color='#%06x' underline='single'>Upgrade to version %s</span>"
 #~ msgstr ""
 #~ "\n"
 #~ "<span color='#%06x' underline='single'>Actualizar a la versión %s</span>"
-
 #~ msgid ""
 #~ "<span color='#%06x' underline='single' size='larger'>Install %s Now</span>"
 #~ msgstr ""
 #~ "<span color='#%06x' underline='single' size='larger'>Instalar %s Ahora</"
 #~ "span>"
-
 #~ msgid ""
 #~ "\n"
 #~ "<small>Version: %s</small>"
 #~ msgstr ""
 #~ "\n"
 #~ "<small>Versión: %s</small>"
-
 #~ msgid "failed to download: invalid package_id and/or directory"
 #~ msgstr "falló la descarga: id de paquete inválido y/o directorio"
-
 #~ msgid "Could not find a valid metadata file"
 #~ msgstr "No se pudo encontrar un archivo de metadatos válido"
-
 #~ msgid "Okay to download the additional packages"
 #~ msgstr "Listo para descargar los paquetes adicionales"
-
 #~ msgid "You need to specify the pack name and packages to be packed\n"
 #~ msgstr "Debe especificar el nombre de grupo y los paquetes a agrupar\n"
-
 #~ msgid ""
 #~ "Invalid name for the service pack, Specify a name with .servicepack "
 #~ "extension\n"
 #~ msgstr ""
 #~ "Nombre inválido para el paquete de servicio. Especifique un nombre con la "
 #~ "extensión .servicepack\n"
-
 #~ msgid "Authentication is required to install a local file"
 #~ msgstr "Se requiere autenticación para instalar un archivo local"
-
 #~ msgid "Authentication is required to install a security signature"
 #~ msgstr "Se requiere autenticación para instalar una firma de seguridad"
-
 #~ msgid "Authentication is required to update all packages"
 #~ msgstr "Se requiere autenticación para actualizar todos los paquetes"
-
 #~ msgid "Install security signature"
 #~ msgstr "Instalar firma de seguridad"
-
 #~ msgid "Refresh package lists"
 #~ msgstr "Refrescar lista de paquetes"
-
 #~ msgid "Update all packages"
 #~ msgstr "Actualizar todos los paquetes"
-
 #~ msgid ""
 #~ "Could not find a package with that name to install, or package already "
 #~ "installed"
 #~ msgstr ""
 #~ "No se pudo encontrar un paquete con ese nombre para instalar, o el "
 #~ "paquete ya está instalado"
-
 #~ msgid "Could not find a package with that name to update"
 #~ msgstr "No se pudo encontrar un paquete con ese nombre para actualizar"
-
 #~ msgid "Could not find a description for this package"
 #~ msgstr "No se pudo encontrar una descripcion para este paquete"
-
 #~ msgid "You need to specify a package to find the description for"
 #~ msgstr "Debe especificar un paquete para el que buscar la descripción"
+
commit fa6527d04e76c5cc116aa3fadb68aa8e8a0f0cbb
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Feb 20 15:21:02 2009 +0000

    trivial: fix a build issue with the documentation

diff --git a/docs/api/spec/pk-introduction.xml b/docs/api/spec/pk-introduction.xml
index 7696c54..d67838e 100644
--- a/docs/api/spec/pk-introduction.xml
+++ b/docs/api/spec/pk-introduction.xml
@@ -76,7 +76,7 @@
         daemon debugging output can be observed.
       </para>
     </sect2>
-    <sect2 id="config-main-timeout">
+    <sect2 id="config-main-shutdown-timeout">
       <title>ShutdownTimeout</title>
       <para>
         This is the time that the daemon waits when idle before shutting down.
@@ -86,13 +86,13 @@
         although the daemon will start and stop less often.
       </para>
     </sect2>
-    <sect2 id="config-main-timeout">
+    <sect2 id="config-main-use-syslog">
       <title>UseSyslog</title>
       <para>
         Syslog is used to audit and log actions wherever its available.
       </para>
     </sect2>
-    <sect2 id="config-main-default">
+    <sect2 id="config-main-default-backend">
       <title>DefaultBackend</title>
       <para>
         The default backend that the daemon should use.
commit bf1b34e6dd9ebaf2d5c0892c54212fb134ab905b
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Feb 20 15:04:46 2009 +0000

    bugfix: don't use an local error in pkcon list-install else we'll fail to free it, and it's non-fatal

diff --git a/client/pk-console.c b/client/pk-console.c
index 8346b4b..bd10a13 100644
--- a/client/pk-console.c
+++ b/client/pk-console.c
@@ -1316,8 +1316,9 @@ pk_console_list_install (PkClient *client, const gchar *file, GError **error)
 	g_print ("%s:\n", _("To install"));
 	for (i=0; i<length; i++) {
 		obj = pk_package_list_get_obj (new, i);
-		g_print ("%i\t%s\n", i+1, obj->id->name);
+		g_print ("%s ", obj->id->name);
 	}
+	g_print ("\n");
 
 	/* resolve */
 	filters = pk_bitfield_from_enums (PK_FILTER_ENUM_NOT_INSTALLED, PK_FILTER_ENUM_NEWEST, -1);
@@ -1325,12 +1326,12 @@ pk_console_list_install (PkClient *client, const gchar *file, GError **error)
 		obj = pk_package_list_get_obj (new, i);
 		/* TRANSLATORS: searching takes some time.... */
 		g_print ("%.0f%%\t%s %s...", (100.0f/length)*i, _("Searching for package: "), obj->id->name);
-		package_id = pk_console_perhaps_resolve (client, filters, obj->id->name, &error_local);
+		package_id = pk_console_perhaps_resolve (client, filters, obj->id->name, NULL);
 		if (package_id == NULL) {
 			/* TRANSLATORS: package was not found -- this is the end of a string ended in ... */
 			g_print (" %s\n", _("not found."));
 		} else {
-			g_print (" %s\n", package_id);
+			g_print (" %s\n", obj->id->version);
 			g_ptr_array_add (array, package_id);
 			/* no need to free */
 		}
commit 1d7eaa073d883a093423b7131cfd9dad948a9f85
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Feb 20 15:03:12 2009 +0000

    bugfix: don't dereference a NULL pointer in pk_console_resolve() which can be done using pkcon list-install

diff --git a/client/pk-tools-common.c b/client/pk-tools-common.c
index dc7d33f..ebd8f9d 100644
--- a/client/pk-tools-common.c
+++ b/client/pk-tools-common.c
@@ -58,7 +58,8 @@ pk_console_resolve (PkBitfield filter, const gchar *package, GError **error)
 	ret = pk_client_resolve (client, filter, packages, &error_local);
 	g_strfreev (packages);
 	if (!ret) {
-		*error = g_error_new (1, 0, _("Internal error: %s"), error_local->message);
+		if (error != NULL)
+			*error = g_error_new (1, 0, _("Internal error: %s"), error_local->message);
 		g_error_free (error_local);
 		goto out;
 	}
@@ -76,14 +77,16 @@ pk_console_resolve (PkBitfield filter, const gchar *package, GError **error)
 		/* reset */
 		ret = pk_client_reset (client, &error_local);
 		if (!ret) {
-			*error = g_error_new (1, 0, _("Internal error: %s"), error_local->message);
+			if (error != NULL)
+				*error = g_error_new (1, 0, _("Internal error: %s"), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
 		/* anything provide it? */
 		ret = pk_client_what_provides (client, filter, PK_PROVIDES_ENUM_ANY, package, &error_local);
 		if (!ret) {
-			*error = g_error_new (1, 0, _("Internal error: %s"), error_local->message);
+			if (error != NULL)
+				*error = g_error_new (1, 0, _("Internal error: %s"), error_local->message);
 			g_error_free (error_local);
 			goto out;
 		}
@@ -110,8 +113,10 @@ pk_console_resolve_package_id (const PkPackageList *list, GError **error)
 	length = pk_package_list_get_size (list);
 
 	if (length == 0) {
-		/* TRANSLATORS: The package was not found in any software sources */
-		*error = g_error_new (1, 0, _("The package could not be found"));
+		if (error != NULL) {
+			/* TRANSLATORS: The package was not found in any software sources */
+			*error = g_error_new (1, 0, _("The package could not be found"));
+		}
 		return NULL;
 	}
 
commit 1b7e562c5548e9c930cad28a9014d228a7894b55
Author: Richard Hughes <richard at hughsie.com>
Date:   Fri Feb 20 15:01:21 2009 +0000

    trivial: more app-install playing

diff --git a/contrib/app-install/.gitignore b/contrib/app-install/.gitignore
index c651369..b4df60c 100644
--- a/contrib/app-install/.gitignore
+++ b/contrib/app-install/.gitignore
@@ -1,6 +1,7 @@
 .deps
 .libs
 *.o
-pk-app-install
+pk-app-install-create
+pk-app-install-remove
 *.db
 
diff --git a/contrib/app-install/Makefile.am b/contrib/app-install/Makefile.am
index 8b39051..c76b7d5 100644
--- a/contrib/app-install/Makefile.am
+++ b/contrib/app-install/Makefile.am
@@ -13,20 +13,23 @@ INCLUDES =						\
 	-DEGG_CONSOLE="\"PK_CONSOLE\""			\
 	-I$(top_srcdir)/lib
 
-sbin_PROGRAMS = pk-app-install
+sbin_PROGRAMS = pk-app-install-create pk-app-install-remove
 
-pk_app_install_SOURCES =				\
+pk_app_install_create_SOURCES =				\
 	egg-debug.c					\
 	egg-debug.h					\
-	pk-app-install.c				\
+	pk-app-install-create.c				\
+	pk-app-install-common.h				\
 	$(NULL)
+pk_app_install_create_LDADD = $(GLIB_LIBS) $(SQLITE_LIBS)
+pk_app_install_create_CFLAGS = $(WARNINGFLAGS_C)
 
-pk_app_install_LDADD =					\
-	$(GLIB_LIBS)					\
-	$(SQLITE_LIBS)					\
-	$(NULL)
-
-pk_app_install_CFLAGS =					\
-	$(WARNINGFLAGS_C)				\
+pk_app_install_remove_SOURCES =				\
+	egg-debug.c					\
+	egg-debug.h					\
+	pk-app-install-remove.c				\
+	pk-app-install-common.h				\
 	$(NULL)
+pk_app_install_remove_LDADD = $(GLIB_LIBS) $(SQLITE_LIBS)
+pk_app_install_remove_CFLAGS = $(WARNINGFLAGS_C)
 
diff --git a/contrib/app-install/pk-app-install-add.c b/contrib/app-install/pk-app-install-add.c
new file mode 100644
index 0000000..357ab74
--- /dev/null
+++ b/contrib/app-install/pk-app-install-add.c
@@ -0,0 +1,345 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <sqlite3.h>
+
+#include "egg-debug.h"
+
+#if PK_BUILD_LOCAL
+#define PK_APP_INSTALL_DEFAULT_DATABASE "./desktop.db"
+#else
+#define PK_APP_INSTALL_DEFAULT_DATABASE DATADIR "/app-install/cache/desktop.db"
+#endif
+
+/**
+ * pk_app_install_create:
+ **/
+static gboolean
+pk_app_install_create (const gchar *cache)
+{
+	gboolean ret = TRUE;
+	gboolean create_file;
+	const gchar *statement;
+	sqlite3 *db = NULL;
+	gint rc;
+
+	/* if the database file was not installed (or was nuked) recreate it */
+	create_file = g_file_test (cache, G_FILE_TEST_EXISTS);
+	if (create_file == TRUE) {
+		egg_warning ("already exists");
+		goto out;
+	}
+
+	egg_debug ("exists: %i", create_file);
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* don't sync */
+	statement = "PRAGMA synchronous=OFF";
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't turn off sync: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	egg_debug ("create");
+	if (create_file == FALSE) {
+		statement = "CREATE TABLE general ("
+			    "application_id TEXT primary key,"
+			    "package_name TEXT,"
+			    "group_id TEXT,"
+			    "repo_name TEXT,"
+			    "application_name TEXT,"
+			    "application_summary TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create general table: %s\n", sqlite3_errmsg (db));
+			ret = FALSE;
+			goto out;
+		}
+		statement = "CREATE TABLE localised ("
+			    "application_id TEXT primary key,"
+			    "application_name TEXT,"
+			    "application_summary TEXT,"
+			    "locale TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create localised table: %s\n", sqlite3_errmsg (db));
+			ret = FALSE;
+			goto out;
+		}
+	}
+
+out:
+	if (db != NULL)
+		sqlite3_close (db);
+	return ret;
+}
+
+/**
+ * pk_app_install_remove_icons_sqlite_cb:
+ **/
+static gint
+pk_app_install_remove_icons_sqlite_cb (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	gint i;
+	gchar *col;
+	gchar *value;
+	const gchar *application_id = NULL;
+	gchar *path;
+	gchar *filename;
+	const gchar *icondir = (const gchar *) data;
+
+	for (i=0; i<argc; i++) {
+		col = col_name[i];
+		value = argv[i];
+		if (g_strcmp0 (col, "application_id") == 0)
+			application_id = value;
+	}
+	if (application_id == NULL)
+		goto out;
+
+	egg_warning ("application_id=%s", application_id);
+	filename = g_strdup_printf ("%s.png", application_id);
+	path = g_build_filename (icondir, "48x48", filename, NULL);
+
+//	g_unlink (path);
+	egg_warning ("path=%s", path);
+
+	g_free (filename);
+	g_free (path);
+out:
+	return 0;
+}
+
+/**
+ * pk_app_install_remove:
+ **/
+static gboolean
+pk_app_install_remove (const gchar *cache, const gchar *icondir, const gchar *repo)
+{
+	gboolean ret = TRUE;
+	gchar *statement = NULL;
+	sqlite3 *db = NULL;
+	gchar *error_msg;
+	gint rc;
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* remove icons */
+	if (icondir != NULL) {
+		statement = g_strdup_printf ("SELECT application_id FROM general WHERE repo_name = '%s'", repo);
+		rc = sqlite3_exec (db, statement, pk_app_install_remove_icons_sqlite_cb, (void*) icondir, &error_msg);
+		g_free (statement);
+		if (rc != SQLITE_OK) {
+			egg_warning ("SQL error: %s\n", error_msg);
+			sqlite3_free (error_msg);
+			return 0;
+		}
+	}
+
+	/* delete from localised (localised has no repo_name, so key off general) */
+	statement = g_strdup_printf ("DELETE FROM localised WHERE EXISTS ( "
+				      "SELECT general.application_id FROM general WHERE "
+				      "general.application_id = general.application_id AND general.repo_name = '%s')", repo);
+//	statement = g_strdup_printf ("SELECT general.application_id FROM general WHERE general.application_id == general.application_id AND general.repo_name == '%s'", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from localised", sqlite3_changes (db));
+	g_free (statement);
+
+	/* delete from general */
+	statement = g_strdup_printf ("DELETE FROM general WHERE repo_name = '%s'", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from general", sqlite3_changes (db));
+	g_free (statement);
+
+	/* reclaim memory */
+	statement = g_strdup ("VACUUM");
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't vacuum: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+out:
+	g_free (statement);
+	if (db != NULL)
+		sqlite3_close (db);
+	return ret;
+}
+
+/**
+ * pk_app_install_add:
+ **/
+static gboolean
+pk_app_install_add (const gchar *cache, const gchar *icondir, const gchar *repo, const gchar *source)
+{
+	egg_warning ("cache=%s, source=%s, repo=%s, icondir=%s", cache, source, repo, icondir);
+	return TRUE;
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+	gboolean verbose = FALSE;
+	GOptionContext *context;
+	gint retval = 0;
+	gchar *action = NULL;
+	gchar *cache = NULL;
+	gchar *repo = NULL;
+	gchar *source = NULL;
+	gchar *icondir = NULL;
+
+	const GOptionEntry options[] = {
+		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+		  _("Show extra debugging information"), NULL },
+		{ "action", 'c', 0, G_OPTION_ARG_STRING, &action,
+		  /* TRANSLATORS: the action is non-localised */
+		  _("The action, one of 'create', 'add', or 'remove'"), NULL},
+		{ "cache", 'c', 0, G_OPTION_ARG_STRING, &cache,
+		  /* TRANSLATORS: if we are specifing a out-of-tree database */
+		  _("Main cache file to use (if not specififed, default is used)"), NULL},
+		{ "source", 's', 0, G_OPTION_ARG_STRING, &source,
+		  /* TRANSLATORS: the source database, typically used for adding */
+		  _("Source cache file to add to the main database"), NULL},
+		{ "icondir", 'i', 0, G_OPTION_ARG_STRING, &icondir,
+		  /* TRANSLATORS: the icon directory */
+		  _("Icon directory"), NULL},
+		{ "repo", 'n', 0, G_OPTION_ARG_STRING, &repo,
+		  /* TRANSLATORS: the repo of the software source, e.g. fedora */
+		  _("Name of the remote repo"), NULL},
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	context = g_option_context_new (NULL);
+	/* TRANSLATORS: tool that gets called when the command is not found */
+	g_option_context_set_summary (context, _("PackageKit Application Database Installer"));
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	egg_debug_init (verbose);
+
+	egg_debug ("cache=%s, source=%s, repo=%s, icondir=%s", cache, source, repo, icondir);
+
+	/* use default */
+	if (cache == NULL) {
+		egg_debug ("cache not specified, using %s", PK_APP_INSTALL_DEFAULT_DATABASE);
+		cache = g_strdup (PK_APP_INSTALL_DEFAULT_DATABASE);
+	}
+
+	if (g_strcmp0 (action, "create") == 0) {
+		pk_app_install_create (cache);
+	} else if (g_strcmp0 (action, "add") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		if (source == NULL) {
+			egg_warning ("A source filename is required");
+			retval = 1;
+			goto out;
+		}
+		if (!g_file_test (source, G_FILE_TEST_EXISTS)) {
+			egg_warning ("The source filename '%s' could not be found", source);
+			retval = 1;
+			goto out;
+		}
+		if (icondir == NULL || !g_file_test (icondir, G_FILE_TEST_IS_DIR)) {
+			egg_warning ("The icon directory '%s' could not be found", icondir);
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_add (cache, icondir, repo, source);
+	} else if (g_strcmp0 (action, "remove") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		if (icondir == NULL || !g_file_test (icondir, G_FILE_TEST_IS_DIR)) {
+			egg_warning ("The icon directory '%s' could not be found", icondir);
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_remove (cache, icondir, repo);
+	} else if (g_strcmp0 (action, "generate") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		if (icondir == NULL || !g_file_test (icondir, G_FILE_TEST_IS_DIR)) {
+			egg_warning ("The icon directory '%s' could not be found", icondir);
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_remove (cache, icondir, repo);
+	} else {
+		egg_warning ("An action is required");
+		retval = 1;
+	}
+
+out:
+	g_free (cache);
+	g_free (repo);
+	g_free (source);
+	g_free (icondir);
+	return 0;
+}
+
diff --git a/contrib/app-install/pk-app-install-common.h b/contrib/app-install/pk-app-install-common.h
new file mode 100644
index 0000000..f74710c
--- /dev/null
+++ b/contrib/app-install/pk-app-install-common.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at 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_APP_INSTALL_COMMON_H
+#define __PK_APP_INSTALL_COMMON_H
+
+#if PK_BUILD_LOCAL
+#define PK_APP_INSTALL_DEFAULT_DATABASE		"./desktop.db"
+#define PK_APP_INSTALL_DEFAULT_ICONDIR		"./icons"
+#else
+#define PK_APP_INSTALL_DEFAULT_DATABASE		DATADIR "/app-install/cache/desktop.db"
+#define PK_APP_INSTALL_DEFAULT_ICONDIR		DATADIR "/app-install/icons"
+#endif
+
+#endif /* __PK_APP_INSTALL_COMMON_H */
diff --git a/contrib/app-install/pk-app-install-create.c b/contrib/app-install/pk-app-install-create.c
new file mode 100644
index 0000000..9373454
--- /dev/null
+++ b/contrib/app-install/pk-app-install-create.c
@@ -0,0 +1,132 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <sqlite3.h>
+
+#include "pk-app-install-common.h"
+#include "egg-debug.h"
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+	gboolean verbose = FALSE;
+	GOptionContext *context;
+	gchar *cache = NULL;
+	gboolean create_file;
+	const gchar *statement;
+	sqlite3 *db = NULL;
+	gint retval;
+	gint rc;
+
+	const GOptionEntry options[] = {
+		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+		  _("Show extra debugging information"), NULL },
+		{ "cache", 'c', 0, G_OPTION_ARG_STRING, &cache,
+		  /* TRANSLATORS: if we are specifing a out-of-tree database */
+		  _("Main database file to use (if not specififed, default is used)"), NULL},
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	context = g_option_context_new (NULL);
+	/* TRANSLATORS: tool that gets called when the command is not found */
+	g_option_context_set_summary (context, _("PackageKit Application Database Installer"));
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	egg_debug_init (verbose);
+
+	/* use default */
+	if (cache == NULL) {
+		egg_debug ("cache not specified, using %s", PK_APP_INSTALL_DEFAULT_DATABASE);
+		cache = g_strdup (PK_APP_INSTALL_DEFAULT_DATABASE);
+	}
+
+	/* if the database file was not installed (or was nuked) recreate it */
+	create_file = g_file_test (cache, G_FILE_TEST_EXISTS);
+	if (create_file == TRUE) {
+		egg_warning ("already exists");
+		goto out;
+	}
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		retval = 1;
+		goto out;
+	}
+
+	/* don't sync */
+	statement = "PRAGMA synchronous=OFF";
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't turn off sync: %s\n", sqlite3_errmsg (db));
+		retval = 1;
+		goto out;
+	}
+
+	/* create */
+	if (create_file == FALSE) {
+		statement = "CREATE TABLE general ("
+			    "application_id TEXT primary key,"
+			    "package_name TEXT,"
+			    "group_id TEXT,"
+			    "repo_name TEXT,"
+			    "application_name TEXT,"
+			    "application_summary TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create general table: %s\n", sqlite3_errmsg (db));
+			retval = 1;
+			goto out;
+		}
+		statement = "CREATE TABLE localised ("
+			    "application_id TEXT primary key,"
+			    "application_name TEXT,"
+			    "application_summary TEXT,"
+			    "locale TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create localised table: %s\n", sqlite3_errmsg (db));
+			retval = 1;
+			goto out;
+		}
+	}
+out:
+	if (db != NULL)
+		sqlite3_close (db);
+	g_free (cache);
+	return retval;
+}
+
diff --git a/contrib/app-install/pk-app-install-generate.c b/contrib/app-install/pk-app-install-generate.c
new file mode 100644
index 0000000..357ab74
--- /dev/null
+++ b/contrib/app-install/pk-app-install-generate.c
@@ -0,0 +1,345 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <sqlite3.h>
+
+#include "egg-debug.h"
+
+#if PK_BUILD_LOCAL
+#define PK_APP_INSTALL_DEFAULT_DATABASE "./desktop.db"
+#else
+#define PK_APP_INSTALL_DEFAULT_DATABASE DATADIR "/app-install/cache/desktop.db"
+#endif
+
+/**
+ * pk_app_install_create:
+ **/
+static gboolean
+pk_app_install_create (const gchar *cache)
+{
+	gboolean ret = TRUE;
+	gboolean create_file;
+	const gchar *statement;
+	sqlite3 *db = NULL;
+	gint rc;
+
+	/* if the database file was not installed (or was nuked) recreate it */
+	create_file = g_file_test (cache, G_FILE_TEST_EXISTS);
+	if (create_file == TRUE) {
+		egg_warning ("already exists");
+		goto out;
+	}
+
+	egg_debug ("exists: %i", create_file);
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* don't sync */
+	statement = "PRAGMA synchronous=OFF";
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't turn off sync: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	egg_debug ("create");
+	if (create_file == FALSE) {
+		statement = "CREATE TABLE general ("
+			    "application_id TEXT primary key,"
+			    "package_name TEXT,"
+			    "group_id TEXT,"
+			    "repo_name TEXT,"
+			    "application_name TEXT,"
+			    "application_summary TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create general table: %s\n", sqlite3_errmsg (db));
+			ret = FALSE;
+			goto out;
+		}
+		statement = "CREATE TABLE localised ("
+			    "application_id TEXT primary key,"
+			    "application_name TEXT,"
+			    "application_summary TEXT,"
+			    "locale TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create localised table: %s\n", sqlite3_errmsg (db));
+			ret = FALSE;
+			goto out;
+		}
+	}
+
+out:
+	if (db != NULL)
+		sqlite3_close (db);
+	return ret;
+}
+
+/**
+ * pk_app_install_remove_icons_sqlite_cb:
+ **/
+static gint
+pk_app_install_remove_icons_sqlite_cb (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	gint i;
+	gchar *col;
+	gchar *value;
+	const gchar *application_id = NULL;
+	gchar *path;
+	gchar *filename;
+	const gchar *icondir = (const gchar *) data;
+
+	for (i=0; i<argc; i++) {
+		col = col_name[i];
+		value = argv[i];
+		if (g_strcmp0 (col, "application_id") == 0)
+			application_id = value;
+	}
+	if (application_id == NULL)
+		goto out;
+
+	egg_warning ("application_id=%s", application_id);
+	filename = g_strdup_printf ("%s.png", application_id);
+	path = g_build_filename (icondir, "48x48", filename, NULL);
+
+//	g_unlink (path);
+	egg_warning ("path=%s", path);
+
+	g_free (filename);
+	g_free (path);
+out:
+	return 0;
+}
+
+/**
+ * pk_app_install_remove:
+ **/
+static gboolean
+pk_app_install_remove (const gchar *cache, const gchar *icondir, const gchar *repo)
+{
+	gboolean ret = TRUE;
+	gchar *statement = NULL;
+	sqlite3 *db = NULL;
+	gchar *error_msg;
+	gint rc;
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* remove icons */
+	if (icondir != NULL) {
+		statement = g_strdup_printf ("SELECT application_id FROM general WHERE repo_name = '%s'", repo);
+		rc = sqlite3_exec (db, statement, pk_app_install_remove_icons_sqlite_cb, (void*) icondir, &error_msg);
+		g_free (statement);
+		if (rc != SQLITE_OK) {
+			egg_warning ("SQL error: %s\n", error_msg);
+			sqlite3_free (error_msg);
+			return 0;
+		}
+	}
+
+	/* delete from localised (localised has no repo_name, so key off general) */
+	statement = g_strdup_printf ("DELETE FROM localised WHERE EXISTS ( "
+				      "SELECT general.application_id FROM general WHERE "
+				      "general.application_id = general.application_id AND general.repo_name = '%s')", repo);
+//	statement = g_strdup_printf ("SELECT general.application_id FROM general WHERE general.application_id == general.application_id AND general.repo_name == '%s'", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from localised", sqlite3_changes (db));
+	g_free (statement);
+
+	/* delete from general */
+	statement = g_strdup_printf ("DELETE FROM general WHERE repo_name = '%s'", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from general", sqlite3_changes (db));
+	g_free (statement);
+
+	/* reclaim memory */
+	statement = g_strdup ("VACUUM");
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't vacuum: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+out:
+	g_free (statement);
+	if (db != NULL)
+		sqlite3_close (db);
+	return ret;
+}
+
+/**
+ * pk_app_install_add:
+ **/
+static gboolean
+pk_app_install_add (const gchar *cache, const gchar *icondir, const gchar *repo, const gchar *source)
+{
+	egg_warning ("cache=%s, source=%s, repo=%s, icondir=%s", cache, source, repo, icondir);
+	return TRUE;
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+	gboolean verbose = FALSE;
+	GOptionContext *context;
+	gint retval = 0;
+	gchar *action = NULL;
+	gchar *cache = NULL;
+	gchar *repo = NULL;
+	gchar *source = NULL;
+	gchar *icondir = NULL;
+
+	const GOptionEntry options[] = {
+		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+		  _("Show extra debugging information"), NULL },
+		{ "action", 'c', 0, G_OPTION_ARG_STRING, &action,
+		  /* TRANSLATORS: the action is non-localised */
+		  _("The action, one of 'create', 'add', or 'remove'"), NULL},
+		{ "cache", 'c', 0, G_OPTION_ARG_STRING, &cache,
+		  /* TRANSLATORS: if we are specifing a out-of-tree database */
+		  _("Main cache file to use (if not specififed, default is used)"), NULL},
+		{ "source", 's', 0, G_OPTION_ARG_STRING, &source,
+		  /* TRANSLATORS: the source database, typically used for adding */
+		  _("Source cache file to add to the main database"), NULL},
+		{ "icondir", 'i', 0, G_OPTION_ARG_STRING, &icondir,
+		  /* TRANSLATORS: the icon directory */
+		  _("Icon directory"), NULL},
+		{ "repo", 'n', 0, G_OPTION_ARG_STRING, &repo,
+		  /* TRANSLATORS: the repo of the software source, e.g. fedora */
+		  _("Name of the remote repo"), NULL},
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	context = g_option_context_new (NULL);
+	/* TRANSLATORS: tool that gets called when the command is not found */
+	g_option_context_set_summary (context, _("PackageKit Application Database Installer"));
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	egg_debug_init (verbose);
+
+	egg_debug ("cache=%s, source=%s, repo=%s, icondir=%s", cache, source, repo, icondir);
+
+	/* use default */
+	if (cache == NULL) {
+		egg_debug ("cache not specified, using %s", PK_APP_INSTALL_DEFAULT_DATABASE);
+		cache = g_strdup (PK_APP_INSTALL_DEFAULT_DATABASE);
+	}
+
+	if (g_strcmp0 (action, "create") == 0) {
+		pk_app_install_create (cache);
+	} else if (g_strcmp0 (action, "add") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		if (source == NULL) {
+			egg_warning ("A source filename is required");
+			retval = 1;
+			goto out;
+		}
+		if (!g_file_test (source, G_FILE_TEST_EXISTS)) {
+			egg_warning ("The source filename '%s' could not be found", source);
+			retval = 1;
+			goto out;
+		}
+		if (icondir == NULL || !g_file_test (icondir, G_FILE_TEST_IS_DIR)) {
+			egg_warning ("The icon directory '%s' could not be found", icondir);
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_add (cache, icondir, repo, source);
+	} else if (g_strcmp0 (action, "remove") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		if (icondir == NULL || !g_file_test (icondir, G_FILE_TEST_IS_DIR)) {
+			egg_warning ("The icon directory '%s' could not be found", icondir);
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_remove (cache, icondir, repo);
+	} else if (g_strcmp0 (action, "generate") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		if (icondir == NULL || !g_file_test (icondir, G_FILE_TEST_IS_DIR)) {
+			egg_warning ("The icon directory '%s' could not be found", icondir);
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_remove (cache, icondir, repo);
+	} else {
+		egg_warning ("An action is required");
+		retval = 1;
+	}
+
+out:
+	g_free (cache);
+	g_free (repo);
+	g_free (source);
+	g_free (icondir);
+	return 0;
+}
+
diff --git a/contrib/app-install/pk-app-install-remove.c b/contrib/app-install/pk-app-install-remove.c
new file mode 100644
index 0000000..d5f3070
--- /dev/null
+++ b/contrib/app-install/pk-app-install-remove.c
@@ -0,0 +1,195 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <sqlite3.h>
+
+#include "pk-app-install-common.h"
+#include "egg-debug.h"
+
+/**
+ * pk_app_install_remove_icons_sqlite_cb:
+ **/
+static gint
+pk_app_install_remove_icons_sqlite_cb (void *data, gint argc, gchar **argv, gchar **col_name)
+{
+	gint i;
+	gchar *col;
+	gchar *value;
+	const gchar *application_id = NULL;
+	gchar *path;
+	gchar *filename;
+	const gchar *icondir = (const gchar *) data;
+
+	for (i=0; i<argc; i++) {
+		col = col_name[i];
+		value = argv[i];
+		if (g_strcmp0 (col, "application_id") == 0)
+			application_id = value;
+	}
+	if (application_id == NULL)
+		goto out;
+
+	egg_warning ("application_id=%s", application_id);
+	filename = g_strdup_printf ("%s.png", application_id);
+	path = g_build_filename (icondir, "48x48", filename, NULL);
+
+//	g_unlink (path);
+	egg_warning ("path=%s", path);
+
+	g_free (filename);
+	g_free (path);
+out:
+	return 0;
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+	gboolean verbose = FALSE;
+	GOptionContext *context;
+	gint retval = 0;
+	gchar *cache = NULL;
+	gchar *repo = NULL;
+	gchar *icondir = NULL;
+	gboolean ret = TRUE;
+	gchar *statement = NULL;
+	sqlite3 *db = NULL;
+	gchar *error_msg;
+	gint rc;
+
+	const GOptionEntry options[] = {
+		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+		  _("Show extra debugging information"), NULL },
+		{ "cache", 'c', 0, G_OPTION_ARG_STRING, &cache,
+		  /* TRANSLATORS: if we are specifing a out-of-tree database */
+		  _("Main cache file to use (if not specififed, default is used)"), NULL},
+		{ "icondir", 'i', 0, G_OPTION_ARG_STRING, &icondir,
+		  /* TRANSLATORS: the icon directory */
+		  _("Icon directory"), NULL},
+		{ "repo", 'n', 0, G_OPTION_ARG_STRING, &repo,
+		  /* TRANSLATORS: the repo of the software source, e.g. fedora */
+		  _("Name of the remote repo"), NULL},
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	context = g_option_context_new (NULL);
+	/* TRANSLATORS: tool that gets called when the command is not found */
+	g_option_context_set_summary (context, _("PackageKit Application Database Installer"));
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	egg_debug_init (verbose);
+
+	/* use default */
+	if (cache == NULL) {
+		egg_debug ("cache not specified, using %s", PK_APP_INSTALL_DEFAULT_DATABASE);
+		cache = g_strdup (PK_APP_INSTALL_DEFAULT_DATABASE);
+	}
+	if (icondir == NULL) {
+		egg_debug ("icondir not specified, using %s", PK_APP_INSTALL_DEFAULT_ICONDIR);
+		icondir = g_strdup (PK_APP_INSTALL_DEFAULT_ICONDIR);
+	}
+
+	/* check */
+	if (repo == NULL) {
+		egg_warning ("A repo name is required");
+		retval = 1;
+		goto out;
+	}
+	if (!g_file_test (icondir, G_FILE_TEST_IS_DIR)) {
+		egg_warning ("The icon directory '%s' could not be found", icondir);
+		retval = 1;
+		goto out;
+	}
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		retval = 1;
+		goto out;
+	}
+
+	/* remove icons */
+	statement = g_strdup_printf ("SELECT application_id FROM general WHERE repo_name = '%s'", repo);
+	rc = sqlite3_exec (db, statement, pk_app_install_remove_icons_sqlite_cb, (void*) icondir, &error_msg);
+	g_free (statement);
+	if (rc != SQLITE_OK) {
+		egg_warning ("SQL error: %s\n", error_msg);
+		sqlite3_free (error_msg);
+		return 0;
+	}
+
+	/* delete from localised (localised has no repo_name, so key off general) */
+	statement = g_strdup_printf ("DELETE FROM localised WHERE EXISTS ( "
+				      "SELECT general.application_id FROM general WHERE "
+				      "general.application_id = general.application_id AND general.repo_name = '%s')", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	g_free (statement);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from localised", sqlite3_changes (db));
+
+	/* delete from general */
+	statement = g_strdup_printf ("DELETE FROM general WHERE repo_name = '%s'", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	g_free (statement);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from general", sqlite3_changes (db));
+
+	/* reclaim memory */
+	statement = g_strdup ("VACUUM");
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't vacuum: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+out:
+	if (db != NULL)
+		sqlite3_close (db);
+	g_free (statement);
+	g_free (cache);
+	g_free (repo);
+	g_free (icondir);
+	return 0;
+}
+
diff --git a/contrib/app-install/pk-app-install.c b/contrib/app-install/pk-app-install.c
deleted file mode 100644
index f8a6263..0000000
--- a/contrib/app-install/pk-app-install.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <glib/gi18n.h>
-#include <sqlite3.h>
-
-#include "egg-debug.h"
-
-#if PK_BUILD_LOCAL
-#define PK_APP_INSTALL_DEFAULT_DATABASE "./desktop.db"
-#else
-#define PK_APP_INSTALL_DEFAULT_DATABASE DATADIR "/app-install/cache/desktop.db"
-#endif
-
-/**
- * pk_app_install_create:
- **/
-static gboolean
-pk_app_install_create (const gchar *cache)
-{
-	gboolean ret = TRUE;
-	gboolean create_file;
-	const gchar *statement;
-	sqlite3 *db = NULL;
-	gint rc;
-
-	/* if the database file was not installed (or was nuked) recreate it */
-	create_file = g_file_test (cache, G_FILE_TEST_EXISTS);
-	if (create_file == TRUE) {
-		egg_warning ("already exists");
-		goto out;
-	}
-
-	egg_debug ("exists: %i", create_file);
-
-	/* open database */
-	rc = sqlite3_open (cache, &db);
-	if (rc) {
-		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
-		ret = FALSE;
-		goto out;
-	}
-
-	/* don't sync */
-	statement = "PRAGMA synchronous=OFF";
-	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
-	if (rc) {
-		egg_warning ("Can't turn off sync: %s\n", sqlite3_errmsg (db));
-		ret = FALSE;
-		goto out;
-	}
-
-	egg_debug ("create");
-	if (create_file == FALSE) {
-		statement = "CREATE TABLE general ("
-			    "application_id TEXT primary key,"
-			    "package_name TEXT,"
-			    "icon_name TEXT,"
-			    "group_id TEXT,"
-			    "repo_name TEXT,"
-			    "application_name TEXT,"
-			    "application_summary TEXT);";
-		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
-		if (rc) {
-			egg_warning ("Can't create general table: %s\n", sqlite3_errmsg (db));
-			ret = FALSE;
-			goto out;
-		}
-		statement = "CREATE TABLE localised ("
-			    "application_id TEXT primary key,"
-			    "application_name TEXT,"
-			    "application_summary TEXT,"
-			    "locale TEXT);";
-		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
-		if (rc) {
-			egg_warning ("Can't create localised table: %s\n", sqlite3_errmsg (db));
-			ret = FALSE;
-			goto out;
-		}
-	}
-
-out:
-	if (db != NULL)
-		sqlite3_close (db);
-	return ret;
-}
-
-/**
- * pk_app_install_remove:
- **/
-static gboolean
-pk_app_install_remove (const gchar *cache, const gchar *repo)
-{
-	gboolean ret = TRUE;
-	gchar *statement = NULL;
-	sqlite3 *db = NULL;
-	gint rc;
-
-	/* open database */
-	rc = sqlite3_open (cache, &db);
-	if (rc) {
-		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
-		ret = FALSE;
-		goto out;
-	}
-
-	/* delete from localised (localised has no repo_name, so key off general) */
-	statement = g_strdup_printf ("DELETE FROM localised WHERE EXISTS ( "
-				      "SELECT general.application_id FROM general WHERE "
-				      "general.application_id = general.application_id AND general.repo_name = '%s')", repo);
-//	statement = g_strdup_printf ("SELECT general.application_id FROM general WHERE general.application_id == general.application_id AND general.repo_name == '%s'", repo);
-	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
-	if (rc) {
-		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
-		ret = FALSE;
-		goto out;
-	}
-	egg_debug ("%i removals from localised", sqlite3_changes (db));
-	g_free (statement);
-
-	/* delete from general */
-	statement = g_strdup_printf ("DELETE FROM general WHERE repo_name = '%s'", repo);
-	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
-	if (rc) {
-		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
-		ret = FALSE;
-		goto out;
-	}
-	egg_debug ("%i removals from general", sqlite3_changes (db));
-	g_free (statement);
-
-	/* reclaim memory */
-	statement = g_strdup ("VACUUM");
-	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
-	if (rc) {
-		egg_warning ("Can't vacuum: %s\n", sqlite3_errmsg (db));
-		ret = FALSE;
-		goto out;
-	}
-
-out:
-	g_free (statement);
-	if (db != NULL)
-		sqlite3_close (db);
-	return ret;
-}
-
-/**
- * pk_app_install_add:
- **/
-static gboolean
-pk_app_install_add (const gchar *cache, const gchar *repo, const gchar *source)
-{
-	egg_debug ("add");
-	return TRUE;
-}
-
-/**
- * main:
- **/
-int
-main (int argc, char *argv[])
-{
-	gboolean verbose = FALSE;
-	GOptionContext *context;
-	gint retval = 0;
-	gchar *action = NULL;
-	gchar *cache = NULL;
-	gchar *repo = NULL;
-	gchar *source = NULL;
-
-	const GOptionEntry options[] = {
-		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
-		  _("Show extra debugging information"), NULL },
-		{ "action", 'c', 0, G_OPTION_ARG_STRING, &action,
-		  /* TRANSLATORS: the action is non-localised */
-		  _("The action, one of 'create', 'add', or 'remove'"), NULL},
-		{ "cache", 'c', 0, G_OPTION_ARG_STRING, &cache,
-		  /* TRANSLATORS: if we are specifing a out-of-tree database */
-		  _("Main cache file to use (if not specififed, default is used)"), NULL},
-		{ "source", 's', 0, G_OPTION_ARG_STRING, &source,
-		  /* TRANSLATORS: the source database, typically used for adding */
-		  _("Source cache file to add to the main database"), NULL},
-		{ "repo", 'n', 0, G_OPTION_ARG_STRING, &repo,
-		  /* TRANSLATORS: the repo of the software source, e.g. fedora */
-		  _("Name of the remote repo"), NULL},
-		{ NULL}
-	};
-
-	setlocale (LC_ALL, "");
-	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
-	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-	textdomain (GETTEXT_PACKAGE);
-
-	context = g_option_context_new (NULL);
-	/* TRANSLATORS: tool that gets called when the command is not found */
-	g_option_context_set_summary (context, _("PackageKit Application Database Installer"));
-	g_option_context_add_main_entries (context, options, NULL);
-	g_option_context_parse (context, &argc, &argv, NULL);
-	g_option_context_free (context);
-
-	egg_debug_init (verbose);
-
-	egg_debug ("cache=%s, source=%s, repo=%s", cache, source, repo);
-
-	/* use default */
-	if (cache == NULL) {
-		egg_debug ("cache not specified, using %s", PK_APP_INSTALL_DEFAULT_DATABASE);
-		cache = g_strdup (PK_APP_INSTALL_DEFAULT_DATABASE);
-	}
-
-	if (g_strcmp0 (action, "create") == 0) {
-		pk_app_install_create (cache);
-	} else if (g_strcmp0 (action, "add") == 0) {
-		if (repo == NULL) {
-			egg_warning ("A repo name is required");
-			retval = 1;
-			goto out;
-		}
-		if (source == NULL) {
-			egg_warning ("A source filename is required");
-			retval = 1;
-			goto out;
-		}
-		if (!g_file_test (source, G_FILE_TEST_EXISTS)) {
-			egg_warning ("The source filename '%s' could not be found", source);
-			retval = 1;
-			goto out;
-		}
-		pk_app_install_remove (cache, repo, source);
-	} else if (g_strcmp0 (action, "remove") == 0) {
-		if (repo == NULL) {
-			egg_warning ("A repo name is required");
-			retval = 1;
-			goto out;
-		}
-		pk_app_install_remove (cache, repo);
-	} else {
-		egg_warning ("An action is required");
-		retval = 1;
-	}
-
-out:
-	g_free (cache);
-	g_free (repo);
-	g_free (source);
-	return 0;
-}
-
diff --git a/docs/app-install-v1.draft b/docs/app-install-v1.draft
index fc4d7d0..08d4e58 100644
--- a/docs/app-install-v1.draft
+++ b/docs/app-install-v1.draft
@@ -85,21 +85,24 @@ STRING locale
 
 TABLE general
 STRING application_id (name of the desktop file, with no extension)
-STRING package_name (to save on expensive SearchFile's)
-STRING icon_name (without path or extension)
+STRING package_name (the package name, e.g. 'nautilus')
 STRING group_id (Categories from desktop file, _not_ PK groups or PK categories)
 STRING repo_name (for adding and removal)
 STRING application_name (Name in desktop file)
 STRING application_summary (Comment in desktop file)
 
+icon_name is not needed as it will be renamed to ${application_id}.png
+
 == Possible Commands ==
-pk-app-install action=create --cache=/usr/share/app-install/cache/desktop.db
-pk-app-install action=add --repo=livna --source=/var/cache/yum/livna-apps.db --cache=/usr/share/app-install/cache/desktop.db
-pk-app-install action=remove --repo=livna --cache=/usr/share/app-install/cache/desktop.db
+pk-app-install-create --cache=/usr/share/app-install/cache/desktop.db
+pk-app-install-add --repo=livna --source=./livna/desktop.db --icondir=./livna/icons --cache=/usr/share/app-install/cache/desktop.db
+pk-app-install-remove --repo=livna --icondir=/usr/share/app-install/icons --cache=/usr/share/app-install/cache/desktop.db
 * need to do the latter then former in a spec file on upgrade
 
 all distro specific stuff to live in backends/, but typically:
 yum-app-install-generate --name=livna --cache=~/livna-apps.db
+pk-app-install-generate --repo=livna --desktopdir=/usr/share/icons --icondir=/usr/share/icons --outputdir=./icons
+
 
 == Open questions ===
 
commit db0b74055b2b5fc131a8aa16d5c4186deb11384e
Merge: 5281a5b... e69e0c2...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Fri Feb 20 15:57:16 2009 +0100

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

commit e69e0c2ad0b4fe6c9d683672ea8b20e056200219
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Fri Feb 20 00:46:15 2009 -0600

    conary:
        add Own progress module
        add percent to update/remove/get-updates/update-system

diff --git a/backends/conary/Makefile.am b/backends/conary/Makefile.am
index 6d7dd38..a605db6 100644
--- a/backends/conary/Makefile.am
+++ b/backends/conary/Makefile.am
@@ -4,9 +4,10 @@ dist_helper_DATA = 			\
 	conaryFilter.py			\
 	conaryCallback.py		\
 	conaryInit.py			\
-	XMLCache.py			\
+	XMLCache.py			    \
 	pkConaryLog.py			\
-	conarypk.py			\
+	conarypk.py			    \
+    conaryProgress.py       \
 	conaryEnums.py
 
 plugindir = $(PK_PLUGIN_DIR)
diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index f54928d..81a17aa 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -33,7 +33,7 @@ from conary.conaryclient import cmdline
 from packagekit.backend import *
 from packagekit.package import *
 from packagekit.progress import PackagekitProgress
-from conaryCallback import UpdateCallback, GetUpdateCallback, RemoveCallback
+from conaryCallback import UpdateCallback, GetUpdateCallback, RemoveCallback, UpdateSystemCallback
 from conaryFilter import *
 from XMLCache import XMLCache as Cache
 from conaryInit import *
@@ -448,12 +448,18 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
     @ExceptionHandler
     def update_system(self):
         self.allow_cancel(True)
+        self.status(STATUS_UPDATE)
+        self.client.setUpdateCallback( UpdateSystemCallback(self, self.cfg) )
         updateItems = self.client.fullUpdateItemList()
         pprint(updateItems)
         applyList = [ (x[0], (None, None), x[1:], True) for x in updateItems ]
-        pprint(applyList)
-        upJob, suggMap = self._get_update(applyList)
-        updJob, suggMap = self._do_update(applyList)
+
+        log.info(">>>>>>>>>> get update >>>>>>>>>>>>")
+        self._get_update(applyList)
+        log.info(">>>>>>>>>> DO Update >>>>>>>>>>>>")
+        self._do_update(applyList)
+        log.info(">>>>>>>>>>END DO Update >>>>>>>>>>>>")
+        self.client.setUpdateCallback(self.callback )
 
 #    @ExceptionHandler
     def refresh_cache(self):
@@ -525,6 +531,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         log.info("========== Remove Packages ============ ")
         log.info( allowDeps ) 
         self.client.setUpdateCallback(RemoveCallback(self, self.cfg))
+        errors = ""
         #for package_id in package_ids.split('%'):
         for package_id in package_ids:
             name, version, flavor, installed = self._findPackage(package_id)
@@ -535,6 +542,10 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
                 name = '-%s' % name
                 self.status(STATUS_REMOVE)
                 self._get_package_update(name, version, flavor)
+                callback = self.client.getUpdateCallback()
+                if callback.error:
+                    self.error(ERROR_DEP_RESOLUTION_FAILED,', '.join(callback.error))
+                        
                 self._do_package_update(name, version, flavor)
             else:
                 self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'The package was not found')
diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index 2dd99c8..8ba4db1 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -19,11 +19,175 @@
 # Copyright (C) 2008 Richard Hughes <richard at hughsie.com>
 from conary import callbacks
 from packagekit.backend import *
-from packagekit.progress import PackagekitProgress
+from conaryProgress import PackagekitProgress
 from pkConaryLog import log
 
 MEGA = 1048576.0
 
+class UpdateSystemCallback(callbacks.UpdateCallback):
+    def __init__(self, backend, cfg=None):
+        callbacks.UpdateCallback.__init__(self)
+        log.info("==== callback ==== ")
+        if cfg:
+            self.setTrustThreshold(cfg.trustThreshold)
+
+        self.backend = backend
+        self.currentJob = None
+        self.smallUpdate = False
+        self.error = []
+        self.progress = PackagekitProgress()
+        self.progress.set_steps([ 30,60,65 ]  )
+    #1
+    #3
+    def requestingChangeSet(self):
+        log.info("Callback UpdateSystem........ STATUS_REQUEST changeset ")
+        self.backend.status(STATUS_DOWNLOAD)
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+    #2
+    def downloadingChangeSet(self, got, need):
+        log.info("Callback UpdateSystem........ STATUS_DOWNLOAD  Changeset %.2f percent %.2f/%.2f Mbytes" % ( got*100/float(need), got/MEGA,need/MEGA) )
+        self.progress.set_subpercent( got*100 / float(need) )
+        self.backend.percentage( self.progress.percent )
+        log.info( "%s percent" % self.progress.percent)
+
+    #4
+    def resolvingDependencies(self):
+        log.info("Callback UpdateSystem........ STATUS_DEP_RESOLVE ")
+        self.backend.percentage(self.progress.percent)
+        self.backend.status(STATUS_DEP_RESOLVE)
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+
+    def setChangesetHunk(self, num, total):
+        log.info("callback. .......... set Changeset HUnk %s/%s" % (num, total ) )
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+
+    def setUpdateHunk(self, hunk, hunkCount):
+        log.info("callback. .......... set update HUnk %s/%s" % ( hunk, hunkCount))
+        self.progress.step()
+
+        if hunk < hunkCount:
+            p = hunk / float(hunkCount) * 100.0
+            self.progress.set_subpercent(p)
+        else:
+            self.smallUpdate = True
+
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+
+    def setUpdateJob(self, job):
+        log.info("callback. .......... set update Job")
+        self.currentJob = job
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+
+    def creatingRollback(self):
+        #self.backend.status('Creating Rollback')
+        log.info("Callback ........ STATUS_ROLLBACK  ")
+        self.backend.status(STATUS_ROLLBACK)
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+
+
+    def preparingUpdate(self, troveNum, troveCount, add=0):
+        log.info("callback ....... preparing Update  trove %s/%s" % (troveNum, troveCount) )
+        #self.progress.step()
+        if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
+            return
+
+        if troveNum > 0 and troveCount > 0:
+            sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
+            self.progress.set_subpercent(sub_percent)
+
+        self.backend.percentage(self.progress.percent)
+        if troveNum > 0:
+            troveNum -= 1
+        log.info("currentJob")
+        log.info(self.currentJob[troveNum])
+        job = self.currentJob[troveNum]
+        name = job[0]
+        oldVersion, oldFlavor = job[1]
+        newVersion, newFlavor = job[2]
+        #log.info("JOB>>>>>>>> %s " % str(job) )
+        if oldVersion and newVersion:
+            log.info("Callback ........ STATUS_UPDATE preparing Update ")
+            self.backend.status(STATUS_UPDATE)
+            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
+            self.backend.package(package_id, INFO_UPDATING, '')
+        elif oldVersion and not newVersion:
+            log.info("Callback ........ STATUS_REMOVE preparing Update ")
+            self.backend.status(STATUS_REMOVE)
+            package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
+            self.backend.package(package_id, INFO_REMOVING, '')
+        elif not oldVersion and newVersion:
+            log.info("Callback ........ STATUS_INSTALL preparing Update")
+            self.backend.status(STATUS_INSTALL)
+            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
+            self.backend.package(package_id, INFO_INSTALLING, '')
+        log.info(self.progress.percent)
+
+    def creatingDatabaseTransaction(self, troveNum, troveCount):
+        log.info("callback. .......... creating Database Transactions")
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+        self.preparingUpdate(troveNum, troveCount, add=troveCount)
+
+    def committingTransaction(self):
+        #self.backend.status('Committing Transaction')
+        log.info("Callback ........ STATUS_COMMIT  transactions ")
+
+        self.backend.status(STATUS_COMMIT)
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+
+    def updateDone(self):
+        log.info("callback. ..........  update done")
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        self.currentJob = None
+        log.info(self.progress.percent)
+
+    def downloadingFileContents(self, got, need):
+        #self.backend.status('Downloading files for changeset')
+        log.info("Callback ........ STATUS_DOWNLOAD  FIle Contents %s " %  str( got*100/need  ))
+        self.backend.status(STATUS_DOWNLOAD)
+        #self.backend.sub_percentage(got*100/need)
+
+    def requestingFileContents(self):
+        #self.backend.status('Requesting File Contents')
+        log.info("Callback ........ STATUS_REQUEST request File contents ")
+        self.backend.status(STATUS_REQUEST)
+
+    def removeFiles(self, filenum, total):
+        log.info("Callback ........ STATUS_REMOVE %s/%sfiles" %( filenum, total) )
+        self.backend.status(STATUS_REMOVE)
+        self.preparingUpdate(filenum, total, add=total)
+    
+    def done(self):
+        #self.backend.status('Done')
+    #    self.progress.step()
+        log.info("DONEEEEEEEEEEEE")
+ 
+    def warning(self, msg, *args, **kwargs):
+        e = msg %args
+        log.error("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
+        log.error(e)
+        self.backend.error(ERROR_DEP_RESOLUTION_FAILED, e, False )
+        
+    def tagHandlerOutput(self, tag, msg, stderr = False):
+        pass
+
+    def troveScriptOutput(self, typ, msg):
+        pass
+
 class GetUpdateCallback(callbacks.UpdateCallback):
     def __init__(self, backend, cfg=None):
         callbacks.UpdateCallback.__init__(self)
@@ -36,7 +200,7 @@ class GetUpdateCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([1,2,50, 100 ]  )
+        self.progress.set_steps([1,50, 100 ]  )
     # 1 >> downloadingChangeSet
     # 2 >> downloadingChangeSet
     def requestingChangeSet(self):
@@ -47,7 +211,7 @@ class GetUpdateCallback(callbacks.UpdateCallback):
         self.progress.step()
 
     def downloadingChangeSet(self, got, need):
-        log.info("Callback getUpdates. Changeset %s percent of %s/%s bytes" % ( int( got*100/float(need)), got/MEGA,need/MEGA) )
+        log.info("Callback getUpdates. Changeset %s percent of %.2f/%.2f bytes" % ( int( got*100/float(need)), got/MEGA,need/MEGA) )
         self.backend.status(STATUS_DOWNLOAD)
         self.progress.set_subpercent( got*100 / float(need) )
         self.backend.percentage( self.progress.percent )
@@ -76,9 +240,16 @@ class UpdateCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([ 0,5,8,10,12,20,35,80,90,100 ]  )
-    # 1
-    # 4
+        self.progress.set_steps([ 
+            1, # requestingChangeSet 1
+            50, # resolveDeps2
+            51, # SetChangesetHunk3
+            52, # requestingChangeSet4
+            80,# setUpdateHUnk5
+            81,# setUpdateJob6
+            ]  )
+    # 1 >> download
+    # 4 >> download
     def requestingChangeSet(self):
         log.info("Callback ........ STATUS_REQUEST changeset ")
         self.backend.status(STATUS_DOWNLOAD)
@@ -87,14 +258,14 @@ class UpdateCallback(callbacks.UpdateCallback):
         self.progress.step()
 
     def downloadingChangeSet(self, got, need):
-        log.info("Callback ........ STATUS_DOWNLOAD  Changeset %s percent %s/%s bytes" % ( got*100/float(need), got/MEGA,need/MEGA) )
+        log.info("Callback ........ STATUS_DOWNLOAD  Changeset %s percent %.2f/%.2f bytes" % ( got*100/float(need), got/MEGA,need/MEGA) )
         self.progress.set_subpercent( got*100 / float(need) )
         self.backend.percentage( self.progress.percent )
         log.info( "%s percent" % self.progress.percent)
 
 
 
-    # 2 
+    # 2  
     def resolvingDependencies(self):
         #self.backend.status('Resolving Dependencies')
         log.info("Callback ........ STATUS_DEP_RESOLVE ")
@@ -127,16 +298,14 @@ class UpdateCallback(callbacks.UpdateCallback):
     def setUpdateJob(self, job):
         log.info("callback. .......... set update Job")
         self.currentJob = job
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
 
-    #7
+    #7 >> preparing update
     def creatingRollback(self):
         #self.backend.status('Creating Rollback')
         log.info("Callback ........ STATUS_ROLLBACK  ")
         self.backend.status(STATUS_ROLLBACK)
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
 
@@ -166,11 +335,6 @@ class UpdateCallback(callbacks.UpdateCallback):
             self.backend.status(STATUS_UPDATE)
             package_id = self.backend.get_package_id(name, newVersion, newFlavor)
             self.backend.package(package_id, INFO_UPDATING, '')
-        elif oldVersion and not newVersion:
-            log.info("Callback ........ STATUS_REMOVE preparing Update ")
-            self.backend.status(STATUS_REMOVE)
-            package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
-            self.backend.package(package_id, INFO_REMOVING, '')
         elif not oldVersion and newVersion:
             log.info("Callback ........ STATUS_INSTALL preparing Update")
             self.backend.status(STATUS_INSTALL)
@@ -180,7 +344,6 @@ class UpdateCallback(callbacks.UpdateCallback):
     #8
     def creatingDatabaseTransaction(self, troveNum, troveCount):
         log.info("callback. .......... creating Database Transactions")
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
         self.preparingUpdate(troveNum, troveCount, add=troveCount)
@@ -198,7 +361,6 @@ class UpdateCallback(callbacks.UpdateCallback):
     #10
     def updateDone(self):
         log.info("callback. ..........  update done")
-        self.progress.step()
         self.backend.percentage(self.progress.percent)
         self.currentJob = None
         log.info(self.progress.percent)
@@ -253,7 +415,7 @@ class RemoveCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([ 0,5,10,15,20,60,75,100 ]  )
+        self.progress.set_steps([ 2,5,7,8,90,100 ]  )
      # 1
     def resolvingDependencies(self):
         #self.backend.status('Resolving Dependencies')
@@ -272,8 +434,6 @@ class RemoveCallback(callbacks.UpdateCallback):
     #3
     def setUpdateHunk(self, hunk, hunkCount):
         log.info("callback. .......... set update HUnk %s/%s" % ( hunk, hunkCount))
-        self.progress.step()
-
         if hunk < hunkCount:
             p = hunk / float(hunkCount) * 100.0
             self.progress.set_subpercent(p)
@@ -295,26 +455,23 @@ class RemoveCallback(callbacks.UpdateCallback):
         log.info("Callback ........ STATUS_ROLLBACK  ")
         self.backend.status(STATUS_ROLLBACK)
         self.progress.step()
-        self.backend.percentage(self.progress.percent)
+        #self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
      #6
     def removeFiles(self, filenum, total):
-        log.info("Callback ........ STATUS_REMOVE %s/%sfiles" %( filenum, total) )
+        log.info("Callback ........ STATUS_REMOVE %s percent %s/%s files" %(filenum*100/float(total), filenum, total) )
+        self.progress.set_subpercent( filenum*100/float(total) )
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
         self.backend.status(STATUS_REMOVE)
         self.preparingUpdate(filenum, total, add=total)
 
-   #7
     def preparingUpdate(self, troveNum, troveCount, add=0):
         log.info("callback ....... preparing Update  trove %s/%s" % (troveNum, troveCount) )
         #self.progress.step()
         if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
             return
 
-        if troveNum > 0 and troveCount > 0:
-            sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
-            self.progress.set_subpercent(sub_percent)
-
-        self.backend.percentage(self.progress.percent)
         log.info("currentJob %s" % troveNum)
         log.info("job %s" % self.currentJob)
         if len(self.currentJob) > troveNum:
@@ -335,12 +492,7 @@ class RemoveCallback(callbacks.UpdateCallback):
             self.backend.status(STATUS_REMOVE)
             package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
             self.backend.package(package_id, INFO_REMOVING, '')
-        elif not oldVersion and newVersion:
-            log.info("Callback ........ STATUS_INSTALL preparing Update")
-            self.backend.status(STATUS_INSTALL)
-            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
-            self.backend.package(package_id, INFO_INSTALLING, '')
-        log.info(self.progress.percent)
+
     def creatingDatabaseTransaction(self, troveNum, troveCount):
         log.info("callback. .......... creating Database Transactions")
         self.progress.step()
@@ -365,14 +517,14 @@ class RemoveCallback(callbacks.UpdateCallback):
         log.info(self.progress.percent)
   
     def done(self):
-        #self.backend.status('Done')
     #    self.progress.step()
-        log.info("DONEEEEEEEEEEEE")
+        log.info("Some Problem ...............>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
+        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
  
     def warning(self, msg, *args, **kwargs):
         e = msg %args
+        self.error.append(e)
         log.error("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
-        log.error(e)
-        self.backend.error(ERROR_DEP_RESOLUTION_FAILED, e, False )
+        log.error( args )
         
  
diff --git a/backends/conary/conaryProgress.py b/backends/conary/conaryProgress.py
new file mode 100644
index 0000000..644ba98
--- /dev/null
+++ b/backends/conary/conaryProgress.py
@@ -0,0 +1,105 @@
+# 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.
+#
+# Copyright (C) 2008
+#    Richard Hughes <richard at hughsie.com>
+
+class PackagekitProgress:
+    '''
+    Progress class there controls the total progress of a transaction
+    the transaction is divided in n milestones. the class contains a subpercentage
+    of the current step (milestone n -> n+1) and the percentage of the whole transaction
+
+    Usage:
+
+    from packagekit import PackagekitProgress
+
+    steps = [10, 30, 50, 70] # Milestones in %
+    progress = PackagekitProgress()
+    progress.set_steps(steps)
+    for milestone in range(len(steps)):
+        # do the action is this step
+        for i in range(100):
+            # do some action
+            progress.set_subpercent(i+1)
+            print "progress : %s " % progress.percent
+        progress.step() # step to next milestone
+
+
+    *** NOTE! a BIGNOTE:
+        if you do a progress.step() and if the next is a sub_percent()  _not print the percente_ first
+        set_subpercent an then print progress.percent.
+    '''
+
+    #TODO: Add support for elapsed/remaining time
+
+    def __init__(self):
+        self.percent = 0
+        self.steps = []
+        self.current_step = 0
+        self.subpercent = 0
+
+    def set_steps(self, steps):
+        '''
+        Set the steps for the whole transaction
+        @param steps: list of int representing the percentage of each step in the transaction
+        '''
+        self.reset()
+        self.steps = steps
+        self.current_step = 0
+
+    def reset(self):
+        self.percent = 0
+        self.steps = []
+        self.current_step = 0
+        self.subpercent = 0
+
+    def step(self):
+        '''
+        Step to the next step in the transaction
+        '''
+        if self.current_step < len(self.steps)-1:
+            self.current_step += 1
+            self.percent = self.steps[self.current_step]
+            self.subpercent = 0
+        else:
+            self.percent = 100
+            self.subpercent = 0
+
+    def set_subpercent(self, pct):
+        '''
+        Set subpercentage and update percentage
+        '''
+        self.subpercent = pct
+        self._update_percent()
+
+    def _update_percent(self):
+        '''
+        Increment percentage based on current step and subpercentage
+        '''
+        if self.current_step == 0:
+            startpct = 0
+        else:
+            startpct = self.steps[self.current_step-1]
+        if self.current_step < len(self.steps)-1:
+            endpct = self.steps[self.current_step]
+        else:
+            endpct = 100
+        deltapct = endpct -startpct
+        f = float(self.subpercent)/100.0
+        incr = int(f*deltapct)
+        self.percent = startpct + incr
+
commit 5281a5b43ebc837c6e883b70aa720615233efe9b
Merge: 6fe3a08... 28085b0...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Fri Feb 20 05:06:42 2009 +0100

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

commit 9b898a676135d9c181f88fd4df6554309cf58d06
Merge: 1b8b519... 28085b0...
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Wed Feb 18 23:04:50 2009 -0600

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

commit 6fe3a080792ce881cf5a8280d4e003a5abac5d90
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Thu Feb 19 05:07:23 2009 +0100

    APT: Add script to extract information from app-install desktop files

diff --git a/backends/apt/update-packagekit-app-data b/backends/apt/update-packagekit-app-data
new file mode 100755
index 0000000..b0e6a57
--- /dev/null
+++ b/backends/apt/update-packagekit-app-data
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+# update-packagekit-app-data - Generate a cache of mime type and codec handlers
+# Authors: Michael Vogt <mvo at ubuntu.com>
+#          Sebastian Heinlein <devel at glatzor.de>
+
+import sys
+import glob
+import os
+import os.path
+import re
+import sys
+
+from optparse import OptionParser
+
+import gdbm
+
+try:
+    import xdg.DesktopEntry
+except ImportError, e:
+    print "WARNING: can not import xdg.DesktopEntry, aborting"
+    sys.exit(0)
+
+def generate_mime_map(desktop_dir, cache_dir):
+    dicts = { 'mime':{}, 'codec':{} }
+
+    def record_provider(de, cp, defield,dictname):
+        try: 
+            keys = de.get(defield, list=True)
+        except keyError: 
+            return
+        if not keys: return
+        dict = dicts[dictname]
+        for key in keys:
+            # gst-caps support
+            if dictname == 'codec' and ',' in key:
+                key = key.split(",")[0]
+            try:
+                l = dict[key]
+            except KeyError:
+                l = []; dict[key] = l
+            l.append(cp)
+
+    for fn in glob.glob(os.path.join(desktop_dir, 'desktop/*.desktop')):
+        try:
+            de = xdg.DesktopEntry.DesktopEntry(fn)
+        except Exception, e:
+            print >>sys.stderr, "bad .desktop file: %s: %s" % (fn, e)
+        try:
+            component = de.get('X-AppInstall-Section')
+            package = de.get('X-AppInstall-Package')
+        except KeyError:
+            continue
+        cp = component+"/"+package
+        record_provider(de, cp, 'MimeType','mime')
+        record_provider(de, cp, 'X-AppInstall-Codecs','codec')
+
+    for (dictname, dict) in dicts.iteritems():
+        g = gdbm.open(os.path.join(cache_dir,
+                                   dictname+"-map.gdbm"),
+                      'nfu')
+        for (key,l) in dict.iteritems():
+            g[key] = ' '.join(l)
+        g.sync()
+        g.close()
+
+def main():
+    parser = OptionParser()
+    parser.add_option ("-d", "--desktop-dir", action="store",
+                       dest="desktop_dir", 
+                       default="/usr/share/app-install",
+                       help="Directory that contains the desktop files "
+                            "of the applications")
+    parser.add_option ("-c", "--cache-dir", action="store",
+                       dest="cache_dir", 
+                       default="/var/lib/PackageKit",
+                       help="Directory where the data should be cached in")
+    (options, args) = parser.parse_args()
+    for path in (options.desktop_dir, options.cache_dir):
+        if not os.path.isdir(path):
+            print "%s is not a valid directory" % path
+            sys.exit(1)
+    print "Generating mime/codec maps..."
+    generate_mime_map(options.desktop_dir, options.cache_dir)
+
+if __name__ == "__main__":
+    main()
commit 28085b0cb87658d19f1e888f53a5b1a9d21b049b
Author: Scott Reeves <sreeves at novell.com>
Date:   Wed Feb 18 11:38:51 2009 -0700

    zypp - fix up virtual callback methods

diff --git a/backends/zypp/zypp-events.h b/backends/zypp/zypp-events.h
index fa8f52e..1c7973e 100644
--- a/backends/zypp/zypp-events.h
+++ b/backends/zypp/zypp-events.h
@@ -273,7 +273,7 @@ struct RepoProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::P
 
 struct RepoReportReceiver : public zypp::callback::ReceiveReport<zypp::repo::RepoReport>, ZyppBackendReceiver
 {
-	virtual void start (const zypp::ProgressData &data)
+	virtual void start (const zypp::ProgressData &data, const zypp::RepoInfo)
 	{
 		egg_debug ("______________________ RepoReportReceiver::start()________________________");
 		reset_sub_percentage ();
@@ -286,7 +286,7 @@ struct RepoReportReceiver : public zypp::callback::ReceiveReport<zypp::repo::Rep
 		return true;
 	}
 
-	virtual void finish (const zypp::ProgressData &data)
+	virtual void finish (zypp::Repository source, const std::string &task, zypp::repo::RepoReport::Error error, const std::string &reason)
 	{
 		//fprintf (stderr, "\n\n----> RepoReportReceiver::finish()\n");
 	}
@@ -310,7 +310,7 @@ struct DownloadProgressReportReceiver : public zypp::callback::ReceiveReport<zyp
 		}
 	}
 
-	virtual bool progress (int value, const zypp::Url &file)
+	virtual bool progress (int value, const zypp::Url &file, double dbps_avg, double dbps_current)
 	{
 		//fprintf (stderr, "\n\n----> DownloadProgressReportReceiver::progress(), %s:%d\n\n", _package_id == NULL ? "unknown" : _package_id, value);
 		if (_package_id != NULL)
@@ -386,14 +386,12 @@ struct DigestReportReceiver : public zypp::callback::ReceiveReport<zypp::DigestR
 
 struct MediaChangeReportReceiver : public zypp::callback::ReceiveReport<zypp::media::MediaChangeReport>, ZyppBackendReceiver
 {
-        virtual Action requestMedia (zypp::Url &url, unsigned mediaNr, zypp::media::MediaChangeReport::Error error, const std::string &probl)
-        {
-                pk_backend_error_code (_backend,
-                                PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED,
-                                probl.c_str ());
-                // We've to abort here, because there is currently no feasible way to inform the user to insert/change media
-                return ABORT;
-        }
+	virtual Action requestMedia (zypp::Url &url, unsigned mediaNr, const std::string &label, zypp::media::MediaChangeReport::Error error, const std::string &description, const std::vector<std::string> & devices, unsigned int &dev_current)
+	{
+		pk_backend_error_code (_backend, PK_ERROR_ENUM_REPO_NOT_AVAILABLE, description.c_str ());
+		// We've to abort here, because there is currently no feasible way to inform the user to insert/change media
+		return ABORT;
+	}
 };
 
 struct ProgressReportReceiver : public zypp::callback::ReceiveReport<zypp::ProgressReport>, ZyppBackendReceiver
commit fe25123c8ea95416f8640a6b923b548dd1c427f0
Author: Richard Hughes <richard at hughsie.com>
Date:   Wed Feb 18 15:13:34 2009 +0000

    feature: add a pk-app-install binary for manipulating the sqlite cache

diff --git a/configure.ac b/configure.ac
index 1ce261c..e4478ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -393,6 +393,13 @@ fi
 AM_CONDITIONAL(PK_BUILD_GSTREAMER_PLUGIN, test $build_gstreamer_plugin = "yes")
 
 dnl ---------------------------------------------------------------------------
+dnl - Able to build gstreamer plugin
+dnl ---------------------------------------------------------------------------
+AC_ARG_ENABLE(app_install, AS_HELP_STRING([--enable-app-install],[Build application installer functionality]),
+	      enable_app_install=$enableval,enable_app_install=no)
+AM_CONDITIONAL(PK_BUILD_APP_INSTALL, test $enable_app_install = "yes")
+
+dnl ---------------------------------------------------------------------------
 dnl - Able to build GTK module
 dnl ---------------------------------------------------------------------------
 AC_ARG_ENABLE(gtk_module, AS_HELP_STRING([--enable-gtk-module],[Build GTK module functionality]),
@@ -690,6 +697,7 @@ contrib/gstreamer-plugin/Makefile
 contrib/gtk-module/Makefile
 contrib/yum-packagekit/Makefile
 contrib/command-not-found/Makefile
+contrib/app-install/Makefile
 contrib/ruck/Makefile
 contrib/ruck/src/Makefile
 backends/Makefile
@@ -754,6 +762,7 @@ echo "
         GIO support:               ${with_gio}
         Browser plugin:            ${build_browser_plugin}
         GStreamer plugin:          ${build_gstreamer_plugin}
+        Application install:       ${enable_app_install}
         Pango module:              ${build_gtk_module}
         BASH Command not found:    ${build_command_not_found}
         RUCK client:               ${build_ruck}
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index 4e47d70..843479a 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -12,6 +12,10 @@ if PK_BUILD_BROWSER_PLUGIN
 SUBDIRS += browser-plugin
 endif
 
+if PK_BUILD_APP_INSTALL
+SUBDIRS += app-install
+endif
+
 if PK_BUILD_GSTREAMER_PLUGIN
 SUBDIRS += gstreamer-plugin
 endif
diff --git a/contrib/app-install/.gitignore b/contrib/app-install/.gitignore
new file mode 100644
index 0000000..c651369
--- /dev/null
+++ b/contrib/app-install/.gitignore
@@ -0,0 +1,6 @@
+.deps
+.libs
+*.o
+pk-app-install
+*.db
+
diff --git a/contrib/app-install/Makefile.am b/contrib/app-install/Makefile.am
new file mode 100644
index 0000000..8b39051
--- /dev/null
+++ b/contrib/app-install/Makefile.am
@@ -0,0 +1,32 @@
+## We require new-style dependency handling.
+AUTOMAKE_OPTIONS = 1.7
+
+INCLUDES =						\
+	$(GLIB_CFLAGS)					\
+	$(SQLITE_CFLAGS)				\
+	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"		\
+	-DSYSCONFDIR=\""$(sysconfdir)"\" 		\
+	-DDATADIR=\""$(datadir)"\" 		\
+	-DEGG_LOG_FILE=\""$(PK_LOG_DIR)/PackageKit"\"	\
+	-DEGG_VERBOSE="\"PK_VERBOSE\""			\
+	-DEGG_LOGGING="\"PK_LOGGING\""			\
+	-DEGG_CONSOLE="\"PK_CONSOLE\""			\
+	-I$(top_srcdir)/lib
+
+sbin_PROGRAMS = pk-app-install
+
+pk_app_install_SOURCES =				\
+	egg-debug.c					\
+	egg-debug.h					\
+	pk-app-install.c				\
+	$(NULL)
+
+pk_app_install_LDADD =					\
+	$(GLIB_LIBS)					\
+	$(SQLITE_LIBS)					\
+	$(NULL)
+
+pk_app_install_CFLAGS =					\
+	$(WARNINGFLAGS_C)				\
+	$(NULL)
+
diff --git a/contrib/app-install/egg-debug.c b/contrib/app-install/egg-debug.c
new file mode 120000
index 0000000..663c6cd
--- /dev/null
+++ b/contrib/app-install/egg-debug.c
@@ -0,0 +1 @@
+../command-not-found/egg-debug.c
\ No newline at end of file
diff --git a/contrib/app-install/egg-debug.h b/contrib/app-install/egg-debug.h
new file mode 120000
index 0000000..51c7d17
--- /dev/null
+++ b/contrib/app-install/egg-debug.h
@@ -0,0 +1 @@
+../command-not-found/egg-debug.h
\ No newline at end of file
diff --git a/contrib/app-install/pk-app-install.c b/contrib/app-install/pk-app-install.c
new file mode 100644
index 0000000..f8a6263
--- /dev/null
+++ b/contrib/app-install/pk-app-install.c
@@ -0,0 +1,270 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Richard Hughes <richard at hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <sqlite3.h>
+
+#include "egg-debug.h"
+
+#if PK_BUILD_LOCAL
+#define PK_APP_INSTALL_DEFAULT_DATABASE "./desktop.db"
+#else
+#define PK_APP_INSTALL_DEFAULT_DATABASE DATADIR "/app-install/cache/desktop.db"
+#endif
+
+/**
+ * pk_app_install_create:
+ **/
+static gboolean
+pk_app_install_create (const gchar *cache)
+{
+	gboolean ret = TRUE;
+	gboolean create_file;
+	const gchar *statement;
+	sqlite3 *db = NULL;
+	gint rc;
+
+	/* if the database file was not installed (or was nuked) recreate it */
+	create_file = g_file_test (cache, G_FILE_TEST_EXISTS);
+	if (create_file == TRUE) {
+		egg_warning ("already exists");
+		goto out;
+	}
+
+	egg_debug ("exists: %i", create_file);
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* don't sync */
+	statement = "PRAGMA synchronous=OFF";
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't turn off sync: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	egg_debug ("create");
+	if (create_file == FALSE) {
+		statement = "CREATE TABLE general ("
+			    "application_id TEXT primary key,"
+			    "package_name TEXT,"
+			    "icon_name TEXT,"
+			    "group_id TEXT,"
+			    "repo_name TEXT,"
+			    "application_name TEXT,"
+			    "application_summary TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create general table: %s\n", sqlite3_errmsg (db));
+			ret = FALSE;
+			goto out;
+		}
+		statement = "CREATE TABLE localised ("
+			    "application_id TEXT primary key,"
+			    "application_name TEXT,"
+			    "application_summary TEXT,"
+			    "locale TEXT);";
+		rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+		if (rc) {
+			egg_warning ("Can't create localised table: %s\n", sqlite3_errmsg (db));
+			ret = FALSE;
+			goto out;
+		}
+	}
+
+out:
+	if (db != NULL)
+		sqlite3_close (db);
+	return ret;
+}
+
+/**
+ * pk_app_install_remove:
+ **/
+static gboolean
+pk_app_install_remove (const gchar *cache, const gchar *repo)
+{
+	gboolean ret = TRUE;
+	gchar *statement = NULL;
+	sqlite3 *db = NULL;
+	gint rc;
+
+	/* open database */
+	rc = sqlite3_open (cache, &db);
+	if (rc) {
+		egg_warning ("Can't open database: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+	/* delete from localised (localised has no repo_name, so key off general) */
+	statement = g_strdup_printf ("DELETE FROM localised WHERE EXISTS ( "
+				      "SELECT general.application_id FROM general WHERE "
+				      "general.application_id = general.application_id AND general.repo_name = '%s')", repo);
+//	statement = g_strdup_printf ("SELECT general.application_id FROM general WHERE general.application_id == general.application_id AND general.repo_name == '%s'", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from localised", sqlite3_changes (db));
+	g_free (statement);
+
+	/* delete from general */
+	statement = g_strdup_printf ("DELETE FROM general WHERE repo_name = '%s'", repo);
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't remove rows: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+	egg_debug ("%i removals from general", sqlite3_changes (db));
+	g_free (statement);
+
+	/* reclaim memory */
+	statement = g_strdup ("VACUUM");
+	rc = sqlite3_exec (db, statement, NULL, NULL, NULL);
+	if (rc) {
+		egg_warning ("Can't vacuum: %s\n", sqlite3_errmsg (db));
+		ret = FALSE;
+		goto out;
+	}
+
+out:
+	g_free (statement);
+	if (db != NULL)
+		sqlite3_close (db);
+	return ret;
+}
+
+/**
+ * pk_app_install_add:
+ **/
+static gboolean
+pk_app_install_add (const gchar *cache, const gchar *repo, const gchar *source)
+{
+	egg_debug ("add");
+	return TRUE;
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char *argv[])
+{
+	gboolean verbose = FALSE;
+	GOptionContext *context;
+	gint retval = 0;
+	gchar *action = NULL;
+	gchar *cache = NULL;
+	gchar *repo = NULL;
+	gchar *source = NULL;
+
+	const GOptionEntry options[] = {
+		{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+		  _("Show extra debugging information"), NULL },
+		{ "action", 'c', 0, G_OPTION_ARG_STRING, &action,
+		  /* TRANSLATORS: the action is non-localised */
+		  _("The action, one of 'create', 'add', or 'remove'"), NULL},
+		{ "cache", 'c', 0, G_OPTION_ARG_STRING, &cache,
+		  /* TRANSLATORS: if we are specifing a out-of-tree database */
+		  _("Main cache file to use (if not specififed, default is used)"), NULL},
+		{ "source", 's', 0, G_OPTION_ARG_STRING, &source,
+		  /* TRANSLATORS: the source database, typically used for adding */
+		  _("Source cache file to add to the main database"), NULL},
+		{ "repo", 'n', 0, G_OPTION_ARG_STRING, &repo,
+		  /* TRANSLATORS: the repo of the software source, e.g. fedora */
+		  _("Name of the remote repo"), NULL},
+		{ NULL}
+	};
+
+	setlocale (LC_ALL, "");
+	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	textdomain (GETTEXT_PACKAGE);
+
+	context = g_option_context_new (NULL);
+	/* TRANSLATORS: tool that gets called when the command is not found */
+	g_option_context_set_summary (context, _("PackageKit Application Database Installer"));
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+	egg_debug_init (verbose);
+
+	egg_debug ("cache=%s, source=%s, repo=%s", cache, source, repo);
+
+	/* use default */
+	if (cache == NULL) {
+		egg_debug ("cache not specified, using %s", PK_APP_INSTALL_DEFAULT_DATABASE);
+		cache = g_strdup (PK_APP_INSTALL_DEFAULT_DATABASE);
+	}
+
+	if (g_strcmp0 (action, "create") == 0) {
+		pk_app_install_create (cache);
+	} else if (g_strcmp0 (action, "add") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		if (source == NULL) {
+			egg_warning ("A source filename is required");
+			retval = 1;
+			goto out;
+		}
+		if (!g_file_test (source, G_FILE_TEST_EXISTS)) {
+			egg_warning ("The source filename '%s' could not be found", source);
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_remove (cache, repo, source);
+	} else if (g_strcmp0 (action, "remove") == 0) {
+		if (repo == NULL) {
+			egg_warning ("A repo name is required");
+			retval = 1;
+			goto out;
+		}
+		pk_app_install_remove (cache, repo);
+	} else {
+		egg_warning ("An action is required");
+		retval = 1;
+	}
+
+out:
+	g_free (cache);
+	g_free (repo);
+	g_free (source);
+	return 0;
+}
+
diff --git a/docs/app-install-v1.draft b/docs/app-install-v1.draft
index 4894dc3..fc4d7d0 100644
--- a/docs/app-install-v1.draft
+++ b/docs/app-install-v1.draft
@@ -81,21 +81,21 @@ TABLE localised:
 STRING application_id (name of the desktop file, with no extension)
 STRING application_name (Name in desktop file, in locale)
 STRING application_summary (Comment in desktop file, in locale)
-STRING repo_name (for adding and removal)
 STRING locale
 
 TABLE general
 STRING application_id (name of the desktop file, with no extension)
 STRING package_name (to save on expensive SearchFile's)
 STRING icon_name (without path or extension)
-STRING group (Categories from desktop file, _not_ PK groups or PK categories)
+STRING group_id (Categories from desktop file, _not_ PK groups or PK categories)
 STRING repo_name (for adding and removal)
 STRING application_name (Name in desktop file)
 STRING application_summary (Comment in desktop file)
 
 == Possible Commands ==
-pk-app-install-merge-cache --name=livna --source=/var/cache/yum/livna-apps.db --cache=/usr/share/app-install/cache/desktop.db
-pk-app-install-remove-cache --name=livna --cache=/usr/share/app-install/cache/desktop.db
+pk-app-install action=create --cache=/usr/share/app-install/cache/desktop.db
+pk-app-install action=add --repo=livna --source=/var/cache/yum/livna-apps.db --cache=/usr/share/app-install/cache/desktop.db
+pk-app-install action=remove --repo=livna --cache=/usr/share/app-install/cache/desktop.db
 * need to do the latter then former in a spec file on upgrade
 
 all distro specific stuff to live in backends/, but typically:
commit 1b8b51939f31868549cc6c93038f3ec63549eebd
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Wed Feb 18 04:57:00 2009 -0600

    conary: fix step feeling for percent download

diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index fd8d327..2dd99c8 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -76,7 +76,7 @@ class UpdateCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([ 0,5,10,15,20,60,75,80,90,100 ]  )
+        self.progress.set_steps([ 0,5,8,10,12,20,35,80,90,100 ]  )
     # 1
     # 4
     def requestingChangeSet(self):
commit c629201183f3c280ea73358e83d355785812220b
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Wed Feb 18 04:53:28 2009 -0600

    conary: add callback fix for remove/update
            replace status signals invalid

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 1d2fe8e..f54928d 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -506,7 +506,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
                     self.error(ERROR_PACKAGE_ALREADY_INSTALLED,
                         'Package already installed')
 
-                self.status(INFO_INSTALLING)
+                self.status(STATUS_INSTALL)
                 log.info(">>> Prepare Update")
                 self._get_package_update(name, version, flavor)
                 log.info(">>> end Prepare Update")
@@ -533,7 +533,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
                     self.error(ERROR_PACKAGE_NOT_INSTALLED, 'The package %s is not installed' % name)
 
                 name = '-%s' % name
-                self.status(INFO_REMOVING)
+                self.status(STATUS_REMOVE)
                 self._get_package_update(name, version, flavor)
                 self._do_package_update(name, version, flavor)
             else:
diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index 2a259ed..fd8d327 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -253,7 +253,7 @@ class RemoveCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps([ 0,5,10,15,20,60,75,80,90,100 ]  )
+        self.progress.set_steps([ 0,5,10,15,20,60,75,100 ]  )
      # 1
     def resolvingDependencies(self):
         #self.backend.status('Resolving Dependencies')
@@ -315,11 +315,12 @@ class RemoveCallback(callbacks.UpdateCallback):
             self.progress.set_subpercent(sub_percent)
 
         self.backend.percentage(self.progress.percent)
-        if troveNum > 0:
-            troveNum -= 1
-        log.info("currentJob")
-        log.info(self.currentJob[troveNum])
-        job = self.currentJob[troveNum]
+        log.info("currentJob %s" % troveNum)
+        log.info("job %s" % self.currentJob)
+        if len(self.currentJob) > troveNum:
+            job = self.currentJob[troveNum]
+        else:
+            return
         name = job[0]
         oldVersion, oldFlavor = job[1]
         newVersion, newFlavor = job[2]
@@ -345,7 +346,7 @@ class RemoveCallback(callbacks.UpdateCallback):
         self.progress.step()
         self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
-        self.preparingUpdate(troveNum, troveCount, add=troveCount)
+        #self.preparingUpdate(troveNum, troveCount, add=troveCount)
     #8
     def committingTransaction(self):
         #self.backend.status('Committing Transaction')
commit b9d40eeab0bd3c0b3d0613147a25a45134ca83cf
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Wed Feb 18 04:11:42 2009 -0600

    add getUpdate Callback.. work the percent

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index dfdf10a..1d2fe8e 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -33,7 +33,7 @@ from conary.conaryclient import cmdline
 from packagekit.backend import *
 from packagekit.package import *
 from packagekit.progress import PackagekitProgress
-from conaryCallback import UpdateCallback
+from conaryCallback import UpdateCallback, GetUpdateCallback, RemoveCallback
 from conaryFilter import *
 from XMLCache import XMLCache as Cache
 from conaryInit import *
@@ -524,6 +524,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.status(STATUS_RUNNING)
         log.info("========== Remove Packages ============ ")
         log.info( allowDeps ) 
+        self.client.setUpdateCallback(RemoveCallback(self, self.cfg))
         #for package_id in package_ids.split('%'):
         for package_id in package_ids:
             name, version, flavor, installed = self._findPackage(package_id)
@@ -537,6 +538,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
                 self._do_package_update(name, version, flavor)
             else:
                 self.error(ERROR_PACKAGE_ALREADY_INSTALLED, 'The package was not found')
+        self.client.setUpdateCallback(self.callback)
 
     def _get_metadata(self, package_id, field):
         '''
@@ -705,13 +707,15 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         self.allow_cancel(True)
         self.percentage(0)
         self.status(STATUS_INFO)
+        getUpdateC= GetUpdateCallback(self,self.cfg)
+        self.client.setUpdateCallback(getUpdateC)
+        log.info("callback changed")
         log.info("============== get_updates ========================")
         cli = ConaryPk()
         updateItems =cli.cli.fullUpdateItemList()
 #        updateItems = cli.cli.getUpdateItemList()
         for i in updateItems:
             log.info(i[0])
-        log.info("============== end get_updates ========================")
         applyList = [ (x[0], (None, None), x[1:], True) for x in updateItems ]
         log.info("_get_update ....")
         updJob, suggMap = self._get_update(applyList)
@@ -740,7 +744,8 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
             troveTuple.append(version)
             installed = self.check_installed(troveTuple)
             self._show_package(name, version, flavor, INFO_NORMAL)
-        
+        log.info("============== end get_updates ========================")
+        self.client.setUpdateCallback(self.callback)
 
     def _findPackage(self, package_id):
         '''
diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index dd056b5..2a259ed 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -22,8 +22,49 @@ from packagekit.backend import *
 from packagekit.progress import PackagekitProgress
 from pkConaryLog import log
 
-class UpdateCallback(callbacks.UpdateCallback):
+MEGA = 1048576.0
+
+class GetUpdateCallback(callbacks.UpdateCallback):
+    def __init__(self, backend, cfg=None):
+        callbacks.UpdateCallback.__init__(self)
+        log.info("==== callback ==== ")
+        if cfg:
+            self.setTrustThreshold(cfg.trustThreshold)
+
+        self.backend = backend
+        self.currentJob = None
+        self.smallUpdate = False
+        self.error = []
+        self.progress = PackagekitProgress()
+        self.progress.set_steps([1,2,50, 100 ]  )
+    # 1 >> downloadingChangeSet
+    # 2 >> downloadingChangeSet
+    def requestingChangeSet(self):
+        log.info("Callback getUpdates ........ STATUS_REQUEST changeset ")
+        self.backend.status(STATUS_REQUEST)
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+        self.progress.step()
+
+    def downloadingChangeSet(self, got, need):
+        log.info("Callback getUpdates. Changeset %s percent of %s/%s bytes" % ( int( got*100/float(need)), got/MEGA,need/MEGA) )
+        self.backend.status(STATUS_DOWNLOAD)
+        self.progress.set_subpercent( got*100 / float(need) )
+        self.backend.percentage( self.progress.percent )
+        log.info( "%s percent" % self.progress.percent)
+    # 3
+    def resolvingDependencies(self):
+        #self.backend.status('Resolving Dependencies')
+        self.backend.status(STATUS_DEP_RESOLVE)
+        self.progress.step()
+        log.info("Callback getUpdates........ STATUS_DEP_RESOLVE ")
+        self.backend.percentage(self.progress.percent)
+        log.info("do a step>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
 
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+  
+class UpdateCallback(callbacks.UpdateCallback):
     def __init__(self, backend, cfg=None):
         callbacks.UpdateCallback.__init__(self)
         log.info("==== callback ==== ")
@@ -46,7 +87,7 @@ class UpdateCallback(callbacks.UpdateCallback):
         self.progress.step()
 
     def downloadingChangeSet(self, got, need):
-        log.info("Callback ........ STATUS_DOWNLOAD  Changeset %s percent %s/%s bytes" % ( got*100/float(need), got,need) )
+        log.info("Callback ........ STATUS_DOWNLOAD  Changeset %s percent %s/%s bytes" % ( got*100/float(need), got/MEGA,need/MEGA) )
         self.progress.set_subpercent( got*100 / float(need) )
         self.backend.percentage( self.progress.percent )
         log.info( "%s percent" % self.progress.percent)
@@ -184,14 +225,6 @@ class UpdateCallback(callbacks.UpdateCallback):
         #self.backend.status('Done')
     #    self.progress.step()
         log.info("DONEEEEEEEEEEEE")
-        """
-        e = ""
-        for i in self.error:
-            e = e + i
-            log.error(i)
-        if self.error:
-            self.backend.error(ERROR_DEP_RESOLUTION_FAILED, e)
-        """
  
     def warning(self, msg, *args, **kwargs):
         e = msg %args
@@ -208,4 +241,137 @@ class UpdateCallback(callbacks.UpdateCallback):
     def troveScriptFailure(self, typ, errcode):
         pass
 
+class RemoveCallback(callbacks.UpdateCallback):
+    def __init__(self, backend, cfg=None):
+        callbacks.UpdateCallback.__init__(self)
+        log.info("==== callback ==== ")
+        if cfg:
+            self.setTrustThreshold(cfg.trustThreshold)
+
+        self.backend = backend
+        self.currentJob = None
+        self.smallUpdate = False
+        self.error = []
+        self.progress = PackagekitProgress()
+        self.progress.set_steps([ 0,5,10,15,20,60,75,80,90,100 ]  )
+     # 1
+    def resolvingDependencies(self):
+        #self.backend.status('Resolving Dependencies')
+        log.info("Callback ........ STATUS_DEP_RESOLVE ")
+        self.backend.percentage(self.progress.percent)
+        self.backend.status(STATUS_DEP_RESOLVE)
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+    #2
+    def setChangesetHunk(self, num, total):
+        log.info("callback. .......... set Changeset HUnk %s/%s" % (num, total ) )
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+    #3
+    def setUpdateHunk(self, hunk, hunkCount):
+        log.info("callback. .......... set update HUnk %s/%s" % ( hunk, hunkCount))
+        self.progress.step()
+
+        if hunk < hunkCount:
+            p = hunk / float(hunkCount) * 100.0
+            self.progress.set_subpercent(p)
+        else:
+            self.smallUpdate = True
+
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+    #4
+    def setUpdateJob(self, job):
+        log.info("callback. .......... set update Job")
+        self.currentJob = job
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+    #5
+    def creatingRollback(self):
+        #self.backend.status('Creating Rollback')
+        log.info("Callback ........ STATUS_ROLLBACK  ")
+        self.backend.status(STATUS_ROLLBACK)
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+     #6
+    def removeFiles(self, filenum, total):
+        log.info("Callback ........ STATUS_REMOVE %s/%sfiles" %( filenum, total) )
+        self.backend.status(STATUS_REMOVE)
+        self.preparingUpdate(filenum, total, add=total)
+
+   #7
+    def preparingUpdate(self, troveNum, troveCount, add=0):
+        log.info("callback ....... preparing Update  trove %s/%s" % (troveNum, troveCount) )
+        #self.progress.step()
+        if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
+            return
+
+        if troveNum > 0 and troveCount > 0:
+            sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
+            self.progress.set_subpercent(sub_percent)
+
+        self.backend.percentage(self.progress.percent)
+        if troveNum > 0:
+            troveNum -= 1
+        log.info("currentJob")
+        log.info(self.currentJob[troveNum])
+        job = self.currentJob[troveNum]
+        name = job[0]
+        oldVersion, oldFlavor = job[1]
+        newVersion, newFlavor = job[2]
+        #log.info("JOB>>>>>>>> %s " % str(job) )
+        if oldVersion and newVersion:
+            log.info("Callback ........ STATUS_UPDATE preparing Update ")
+            self.backend.status(STATUS_UPDATE)
+            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
+            self.backend.package(package_id, INFO_UPDATING, '')
+        elif oldVersion and not newVersion:
+            log.info("Callback ........ STATUS_REMOVE preparing Update ")
+            self.backend.status(STATUS_REMOVE)
+            package_id = self.backend.get_package_id(name, oldVersion, oldFlavor)
+            self.backend.package(package_id, INFO_REMOVING, '')
+        elif not oldVersion and newVersion:
+            log.info("Callback ........ STATUS_INSTALL preparing Update")
+            self.backend.status(STATUS_INSTALL)
+            package_id = self.backend.get_package_id(name, newVersion, newFlavor)
+            self.backend.package(package_id, INFO_INSTALLING, '')
+        log.info(self.progress.percent)
+    def creatingDatabaseTransaction(self, troveNum, troveCount):
+        log.info("callback. .......... creating Database Transactions")
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+        self.preparingUpdate(troveNum, troveCount, add=troveCount)
+    #8
+    def committingTransaction(self):
+        #self.backend.status('Committing Transaction')
+        log.info("Callback ........ STATUS_COMMIT  transactions ")
+
+        self.backend.status(STATUS_COMMIT)
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        log.info(self.progress.percent)
+    #9
+    def updateDone(self):
+        log.info("callback. ..........  update done")
+        self.progress.step()
+        self.backend.percentage(self.progress.percent)
+        self.currentJob = None
+        log.info(self.progress.percent)
   
+    def done(self):
+        #self.backend.status('Done')
+    #    self.progress.step()
+        log.info("DONEEEEEEEEEEEE")
+ 
+    def warning(self, msg, *args, **kwargs):
+        e = msg %args
+        log.error("<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
+        log.error(e)
+        self.backend.error(ERROR_DEP_RESOLUTION_FAILED, e, False )
+        
+ 
commit 28bfa161725b1c0c2af3050d09535f8eaaa409ab
Merge: afba3b6... 50d3943...
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Wed Feb 18 01:56:10 2009 -0600

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

commit afba3b69d18c1f39ecc14d53f03a6a78250b1391
Merge: 6b8525f... 1fbc53f...
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Tue Feb 17 15:41:43 2009 -0600

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

commit 6b8525f0289ce0329b1e00ebdabdde658e877d10
Author: Andres Vargas ( zodman ) <zodman at foresightlinux.org>
Date:   Tue Feb 17 01:57:11 2009 -0600

    conary: tunning the percent update

diff --git a/backends/conary/conaryBackend.py b/backends/conary/conaryBackend.py
index 70687a5..dfdf10a 100755
--- a/backends/conary/conaryBackend.py
+++ b/backends/conary/conaryBackend.py
@@ -295,6 +295,7 @@ class PackageKitConaryBackend(PackageKitBaseBackend):
         solved = False
         if pkg_dict is None:
             # verifica si esta en repositorios
+            log.info("doing a rq")
             troveTuple = conary_cli.query(package[0])
             if not troveTuple:
                 self.error(ERROR_INTERNAL_ERROR, "Package Not found")
@@ -782,7 +783,7 @@ from pkConaryLog import pdb
 def main():
     backend = PackageKitConaryBackend('')
     log.info("======== argv =========== ")
-    log.info(sys.argv[1:])
+    log.info(sys.argv)
     backend.dispatcher(sys.argv[1:])
 
 if __name__ == "__main__":
diff --git a/backends/conary/conaryCallback.py b/backends/conary/conaryCallback.py
index 712fdd3..dd056b5 100644
--- a/backends/conary/conaryCallback.py
+++ b/backends/conary/conaryCallback.py
@@ -35,7 +35,7 @@ class UpdateCallback(callbacks.UpdateCallback):
         self.smallUpdate = False
         self.error = []
         self.progress = PackagekitProgress()
-        self.progress.set_steps( range( 1, 101,10) )
+        self.progress.set_steps([ 0,5,10,15,20,60,75,80,90,100 ]  )
     # 1
     # 4
     def requestingChangeSet(self):
@@ -47,8 +47,8 @@ class UpdateCallback(callbacks.UpdateCallback):
 
     def downloadingChangeSet(self, got, need):
         log.info("Callback ........ STATUS_DOWNLOAD  Changeset %s percent %s/%s bytes" % ( got*100/float(need), got,need) )
-        #self.progress.set_subpercent( got*100 / float(need) )
-        self.backend.sub_percentage( got*100/float(need) )
+        self.progress.set_subpercent( got*100 / float(need) )
+        self.backend.percentage( self.progress.percent )
         log.info( "%s percent" % self.progress.percent)
 
 
@@ -76,11 +76,11 @@ class UpdateCallback(callbacks.UpdateCallback):
 
         if hunk < hunkCount:
             p = hunk / float(hunkCount) * 100.0
-            #self.progress.set_subpercent(p)
-            self.backend.percentage(self.progress.percent)
+            self.progress.set_subpercent(p)
         else:
             self.smallUpdate = True
 
+        self.backend.percentage(self.progress.percent)
         log.info(self.progress.percent)
     # 6
     def setUpdateJob(self, job):
@@ -102,18 +102,15 @@ class UpdateCallback(callbacks.UpdateCallback):
 
     def preparingUpdate(self, troveNum, troveCount, add=0):
         log.info("callback ....... preparing Update  trove %s/%s" % (troveNum, troveCount) )
-        self.progress.step()
+        #self.progress.step()
         if not self.currentJob or len(self.currentJob) == 0 or troveNum > troveCount:
             return
 
         if troveNum > 0 and troveCount > 0:
             sub_percent = (add + troveNum) / (2 * float(troveCount)) * 100
             self.progress.set_subpercent(sub_percent)
-            self.backend.sub_percentage(sub_percent)
-
-            if self.smallUpdate:
-                self.backend.percentage(self.progress.percent)
 
+        self.backend.percentage(self.progress.percent)
         if troveNum > 0:
             troveNum -= 1
         log.info("currentJob")
commit ffe532d3661e10fcd46d5d1be4d4d1702062a04c
Merge: af113a6... 1ab2a9f...
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 16 18:24:41 2009 +0100

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

commit af113a6d7bcac632508f99fb543f28f85a7b0f92
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 9 06:15:20 2009 +0100

    APT: Remove code which is now merged with python-apt

diff --git a/backends/apt/aptbackend.py b/backends/apt/aptbackend.py
index 700c325..c24d20a 100755
--- a/backends/apt/aptbackend.py
+++ b/backends/apt/aptbackend.py
@@ -196,55 +196,6 @@ class PackageKitCache(apt.cache.Cache):
             yield self._dict[pkgname]
         raise StopIteration
 
-    def isVirtualPackage(self, name):
-        """ 
-        Return True if the package of the given name is a virtual package
-        """
-        try:
-            virtual_pkg = self._cache[name]
-        except KeyError:
-            return False
-        if len(virtual_pkg.VersionList) == 0:
-            return True
-        return False
-
-    def getProvidingPackages(self, virtual):
-        """
-        Return a list of packages which provide the virtual package of the
-        specified name
-        """
-        providers = []
-        try:
-            vp = self._cache[virtual]
-            if len(vp.VersionList) != 0:
-                return providers
-        except KeyError:
-            return providers
-        for pkg in self:
-            v = self._depcache.GetCandidateVer(pkg._pkg)
-            if v == None:
-                continue
-            for p in v.ProvidesList:
-                #print virtual
-                #print p[0]
-                if virtual == p[0]:
-                    # we found a pkg that provides this virtual
-                    # pkg, check if the proivdes is any good
-                    providers.append(pkg)
-                    #cand = self._cache[pkg.name]
-                    #candver = self._cache._depcache.GetCandidateVer(cand._pkg)
-                    #instver = cand._pkg.CurrentVer
-                    #res = apt_pkg.CheckDep(candver.VerStr,oper,ver)
-                    #if res == True:
-                    #    self._dbg(1,"we can use %s" % pkg.name)
-                    #    or_found = True
-                    #    break
-        return providers
-
-    def clear(self):
-        """ Unmark all changes """
-        self._depcache.Init()
-
 
 class DpkgInstallProgress(apt.progress.InstallProgress):
     """
commit 708a1710cd2324fa9e8d47fa1489a543703e6a1d
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 9 05:46:48 2009 +0100

    APT: Install the main Python module into the packagekit package and use a command wrapper to improve the start time (*.pyc)

diff --git a/backends/apt/Makefile.am b/backends/apt/Makefile.am
index 6f390d4..fbec9b2 100644
--- a/backends/apt/Makefile.am
+++ b/backends/apt/Makefile.am
@@ -9,8 +9,12 @@ libpk_backend_apt_la_CFLAGS = $(PK_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
 
 dbusinstancedir = $(LIBEXECDIR)
 dbusinstance_DATA =                                     \
-        aptDBUSBackend.py                               \
-        debfile.py					\
+	pk-backend-apt.py				\
+        $(NULL)
+
+packagekitpythondir = ${PYTHON_PACKAGE_DIR}
+packagekitpython_PYTHON =  				\
+        aptbackend.py					\
         $(NULL)
 
 EXTRA_DIST =                                            \
diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
deleted file mode 100755
index 700c325..0000000
--- a/backends/apt/aptDBUSBackend.py
+++ /dev/null
@@ -1,2236 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-Provides an apt backend to PackageKit
-
-Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
-Copyright (C) 2007 Tom Parker <palfrey at tevp.net>
-Copyright (C) 2008 Sebastian Heinlein <glatzor at ubuntu.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.
-"""
-
-__author__  = "Sebastian Heinlein <devel at glatzor.de>"
-
-import errno
-import fcntl
-import gdbm
-import httplib
-import locale
-import logging
-import optparse
-import os
-import pty
-import re
-import signal
-import shutil
-import socket
-import stat
-import string
-import subprocess
-import sys
-import time
-import threading
-import urllib2
-import warnings
-
-import apt
-import apt.debfile
-import apt_pkg
-import dbus
-import dbus.glib
-import dbus.service
-import dbus.mainloop.glib
-import gobject
-
-from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress, pklog, threaded, serialize
-from packagekit.enums import *
-
-
-warnings.filterwarnings(action='ignore', category=FutureWarning)
-
-PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
-
-apt_pkg.InitConfig()
-apt_pkg.Config.Set("DPkg::Options::", '--force-confdef')
-apt_pkg.Config.Set("DPkg::Options::", '--force-confold')
-
-# Xapian database is optionally used to speed up package description search
-XAPIAN_DB_PATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")
-XAPIAN_DB = XAPIAN_DB_PATH + "/index"
-XAPIAN_DB_VALUES = XAPIAN_DB_PATH + "/values"
-XAPIAN_SUPPORT = False
-try:
-    import xapian
-except ImportError:
-    pass
-else:
-    if os.access(XAPIAN_DB, os.R_OK):
-        pklog.debug("Use XAPIAN for the search")
-        XAPIAN_SUPPORT = True
-
-# SoftwareProperties is required to proivde information about repositories
-try:
-    import softwareproperties.SoftwareProperties
-except ImportError:
-    REPOS_SUPPORT = False
-else:
-    REPOS_SUPPORT = True
-
-# Check if update-manager-core is installed to get aware of the
-# latest distro releases
-try:
-    from UpdateManager.Core.MetaRelease import MetaReleaseCore
-except ImportError:
-    META_RELEASE_SUPPORT = False
-else:
-    META_RELEASE_SUPPORT = True
-
-
-# Set a timeout for the changelog download
-socket.setdefaulttimeout(2)
-
-# Required for daemon mode
-os.putenv("PATH",
-          "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
-# Avoid questions from the maintainer scripts as far as possible
-os.putenv("DEBIAN_FRONTEND", "noninteractive")
-os.putenv("APT_LISTCHANGES_FRONTEND", "none")
-
-# Setup threading support
-gobject.threads_init()
-dbus.glib.threads_init()
-
-# Map Debian sections to the PackageKit group name space
-SECTION_GROUP_MAP = {
-    "admin" : GROUP_ADMIN_TOOLS,
-    "base" : GROUP_SYSTEM,
-    "comm" : GROUP_COMMUNICATION,
-    "devel" : GROUP_PROGRAMMING,
-    "doc" : GROUP_DOCUMENTATION,
-    "editors" : GROUP_PUBLISHING,
-    "electronics" : GROUP_ELECTRONICS,
-    "embedded" : GROUP_SYSTEM,
-    "games" : GROUP_GAMES,
-    "gnome" : GROUP_DESKTOP_GNOME,
-    "graphics" : GROUP_GRAPHICS,
-    "hamradio" : GROUP_COMMUNICATION,
-    "interpreters" : GROUP_PROGRAMMING,
-    "kde" : GROUP_DESKTOP_KDE,
-    "libdevel" : GROUP_PROGRAMMING,
-    "libs" : GROUP_SYSTEM,
-    "mail" : GROUP_INTERNET,
-    "math" : GROUP_SCIENCE,
-    "misc" : GROUP_OTHER,
-    "net" : GROUP_NETWORK,
-    "news" : GROUP_INTERNET,
-    "oldlibs" : GROUP_LEGACY,
-    "otherosfs" : GROUP_SYSTEM,
-    "perl" : GROUP_PROGRAMMING,
-    "python" : GROUP_PROGRAMMING,
-    "science" : GROUP_SCIENCE,
-    "shells" : GROUP_SYSTEM,
-    "sound" : GROUP_MULTIMEDIA,
-    "tex" : GROUP_PUBLISHING,
-    "text" : GROUP_PUBLISHING,
-    "utils" : GROUP_ACCESSORIES,
-    "web" : GROUP_INTERNET,
-    "x11" : GROUP_DESKTOP_OTHER,
-    "unknown" : GROUP_UNKNOWN,
-    "alien" : GROUP_UNKNOWN,
-    "translations" : GROUP_LOCALIZATION,
-    "metapackages" : GROUP_COLLECTIONS }
-
-# Regular expressions to detect bug numbers in changelogs according to the
-# Debian Policy Chapter 4.4. For details see the footnote 16:
-# http://www.debian.org/doc/debian-policy/footnotes.html#f16
-MATCH_BUG_CLOSES_DEBIAN=r"closes:\s*(?:bug)?\#?\s?\d+(?:,\s*(?:bug)?\#?\s?\d+)*"
-MATCH_BUG_NUMBERS=r"\#?\s?(\d+)"
-# URL pointing to a bug in the Debian bug tracker
-HREF_BUG_DEBIAN="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s"
-
-# Regular expression to find cve references
-MATCH_CVE="CVE-\d{4}-\d{4}"
-HREF_CVE="http://web.nvd.nist.gov/view/vuln/detail?vulnId=%s"
-
-def unlock_cache_afterwards(func):
-    '''
-    Make sure that the package cache is unlocked after the decorated function
-    was called
-    '''
-    def wrapper(*args, **kwargs):
-        backend = args[0]
-        func(*args, **kwargs)
-        backend._unlock_cache()
-    wrapper.__name__ = func.__name__
-    return wrapper
-
-
-class PKError(Exception):
-    pass
-
-class PackageManagerFailedPKError(PKError):
-    def __init__(self, msg, pkg, output):
-        self.message = msg
-        self.package = pkg
-        self.output = output
-
-class InstallTimeOutPKError(PKError):
-    pass
-
-class PackageKitCache(apt.cache.Cache):
-    """
-    Enhanced version of the apt.cache.Cache class which supports some features
-    which can only be found in the consolidate branch of python-apt
-    """
-    def __iter__(self):
-        """
-        Let the cache behave like a sorted list of packages
-        """
-        for pkgname in sorted(self._dict.keys()):
-            yield self._dict[pkgname]
-        raise StopIteration
-
-    def isVirtualPackage(self, name):
-        """ 
-        Return True if the package of the given name is a virtual package
-        """
-        try:
-            virtual_pkg = self._cache[name]
-        except KeyError:
-            return False
-        if len(virtual_pkg.VersionList) == 0:
-            return True
-        return False
-
-    def getProvidingPackages(self, virtual):
-        """
-        Return a list of packages which provide the virtual package of the
-        specified name
-        """
-        providers = []
-        try:
-            vp = self._cache[virtual]
-            if len(vp.VersionList) != 0:
-                return providers
-        except KeyError:
-            return providers
-        for pkg in self:
-            v = self._depcache.GetCandidateVer(pkg._pkg)
-            if v == None:
-                continue
-            for p in v.ProvidesList:
-                #print virtual
-                #print p[0]
-                if virtual == p[0]:
-                    # we found a pkg that provides this virtual
-                    # pkg, check if the proivdes is any good
-                    providers.append(pkg)
-                    #cand = self._cache[pkg.name]
-                    #candver = self._cache._depcache.GetCandidateVer(cand._pkg)
-                    #instver = cand._pkg.CurrentVer
-                    #res = apt_pkg.CheckDep(candver.VerStr,oper,ver)
-                    #if res == True:
-                    #    self._dbg(1,"we can use %s" % pkg.name)
-                    #    or_found = True
-                    #    break
-        return providers
-
-    def clear(self):
-        """ Unmark all changes """
-        self._depcache.Init()
-
-
-class DpkgInstallProgress(apt.progress.InstallProgress):
-    """
-    Class to initiate and monitor installation of local package files with dpkg
-    """
-    #FIXME: Use the merged DpkgInstallProgress of python-apt
-    def recover(self):
-        """
-        Run "dpkg --configure -a"
-        """
-        cmd = ["/usr/bin/dpkg", "--status-fd", str(self.writefd),
-               "--root", apt_pkg.Config["Dir"],
-               "--force-confdef", "--force-confold", 
-               "--configure", "-a"]
-        self.run(cmd)
-
-    def install(self, filenames):
-        """
-        Install the given package using a dpkg command line call
-        """
-        cmd = ["/usr/bin/dpkg", "--force-confdef", "--force-confold",
-               "--status-fd", str(self.writefd), 
-               "--root", apt_pkg.Config["Dir"], "-i"]
-        cmd.extend(map(lambda f: str(f), filenames))
-        self.run(cmd)
-
-    def run(self, cmd):
-        """
-        Run and monitor a dpkg command line call
-        """
-        pklog.debug("Executing: %s" % cmd)
-        (self.master_fd, slave) = pty.openpty()
-        fcntl.fcntl(self.master_fd, fcntl.F_SETFL, os.O_NONBLOCK)
-        p = subprocess.Popen(cmd, stdout=slave, stdin=slave)
-        self.child_pid = p.pid
-        res = self.waitChild()
-        return res
-
-    def updateInterface(self):
-        """
-        Process status messages from dpkg
-        """
-        if self.statusfd == None:
-            return
-        try:
-            while not self.read.endswith("\n"):
-                self.read += os.read(self.statusfd.fileno(), 1)
-        except OSError, (error_no, error_str):
-            # resource temporarly unavailable is ignored
-            if error_no not in [errno.EAGAIN, errno.EWOULDBLOCK]:
-                print error_str
-        if self.read.endswith("\n"):
-            statusl = string.split(self.read, ":")
-            if len(statusl) < 3:
-                pklog.warn("got garbage from dpkg: '%s'" % self.read)
-                self.read = ""
-            status = statusl[2].strip()
-            pkg = statusl[1].strip()
-            #print status
-            if status == "error":
-                self.error(pkg, status)
-            elif status == "conffile-prompt":
-                # we get a string like this:
-                # 'current-conffile' 'new-conffile' useredited distedited
-                match = re.search(".+conffile-prompt : '(.+)' '(.+)'",
-                                  self.read)
-                self.conffile(match.group(1), match.group(2))
-            else:
-                pklog.debug("Dpkg status: %s" % status)
-                self.status = status
-            self.read = ""
-
-
-class PackageKitOpProgress(apt.progress.OpProgress):
-    '''
-    Handle the cache opening process
-    '''
-    def __init__(self, backend, prange=(0,100), progress=True):
-        self._backend = backend
-        apt.progress.OpProgress.__init__(self)
-        self.steps = []
-        for v in [0.12, 0.25, 0.50, 0.75, 1.00]:
-            s = prange[0] + (prange[1] - prange[0]) * v
-            self.steps.append(s)
-        self.pstart = float(prange[0])
-        self.pend = self.steps.pop(0)
-        self.pprev = None
-        self.show_progress = progress
-
-    # OpProgress callbacks
-    def update(self, percent):
-        progress = int(self.pstart + percent / 100 * (self.pend - self.pstart))
-        if self.show_progress == True and self.pprev < progress:
-            self._backend.PercentageChanged(progress)
-            self.pprev = progress
-
-    def done(self):
-        self.pstart = self.pend
-        try:
-            self.pend = self.steps.pop(0)
-        except:
-            pklog.warning("An additional step to open the cache is required")
-
-
-class PackageKitFetchProgress(apt.progress.FetchProgress):
-    '''
-    Handle the package download process
-    '''
-    def __init__(self, backend, prange=(0,100)):
-        self._backend = backend
-        apt.progress.FetchProgress.__init__(self)
-        self.pstart = prange[0]
-        self.pend = prange[1]
-        self.pprev = None
-
-    def pulse(self):
-        apt.progress.FetchProgress.pulse(self)
-        # Strange, but we seem to need this to detect a cancel immediately
-        time.sleep(0.01)
-        if self._backend._canceled.isSet():
-            return False
-        progress = int(self.pstart + self.percent/100 * \
-                       (self.pend - self.pstart))
-        if self.pprev < progress:
-            self._backend.PercentageChanged(progress)
-            self.pprev = progress
-        return True
-
-    def start(self):
-        self._backend.StatusChanged(STATUS_DOWNLOAD)
-        self._backend.AllowCancel(True)
-
-    def stop(self):
-        self._backend.PercentageChanged(self.pend)
-        self._backend.AllowCancel(False)
-
-    def mediaChange(self, medium, drive):
-        #FIXME: Raise an expcetion and handle it in _commit_changes
-        #       Strangly _commit_changes does not catch the expcetion
-        self._backend.Message(MESSAGE_UNKNOWN,
-                              "Installing from CD-Rom (%s) is not "
-                              "supported." % medium)
-        return False
-
-
-class PackageKitInstallProgress(apt.progress.InstallProgress):
-    '''
-    Handle the installation and removal process. Bits taken from
-    DistUpgradeViewNonInteractive.
-    '''
-    def __init__(self, backend, prange=(0,100)):
-        apt.progress.InstallProgress.__init__(self)
-        self._backend = backend
-        self.pstart = prange[0]
-        self.pend = prange[1]
-        self.pprev = None
-        self.last_activity = None
-        self.conffile_prompts = set()
-        # insanly long timeout to be able to kill hanging maintainer scripts
-        self.timeout = 10 * 60
-        self.start_time = None
-        self.output = ""
-        self.master_fd = None
-        self.child_pid = None
-
-    def statusChange(self, pkg, percent, status):
-        self.last_activity = time.time()
-        progress = self.pstart + percent/100 * (self.pend - self.pstart)
-        if self.pprev < progress:
-            self._backend.PercentageChanged(int(progress))
-            self.pprev = progress
-        pklog.debug("APT status: %s" % status)
-
-    def startUpdate(self):
-        # The apt system lock was set by _lock_cache() before
-        self._backend._unlock_cache()
-        self._backend.StatusChanged(STATUS_COMMIT)
-        self.last_activity = time.time()
-        self.start_time = time.time()
-
-    def fork(self):
-        pklog.debug("fork()")
-        (pid, self.master_fd) = pty.fork()
-        if pid != 0:
-            fcntl.fcntl(self.master_fd, fcntl.F_SETFL, os.O_NONBLOCK)
-        return pid
-
-    def updateInterface(self):
-        apt.progress.InstallProgress.updateInterface(self)
-        # Collect the output from the package manager
-        try:
-            out = os.read(self.master_fd, 512)
-            self.output = self.output + out
-            pklog.debug("APT out: %s " % out)
-        except OSError:
-            pass
-        # catch a time out by sending crtl+c
-        if self.last_activity + self.timeout < time.time():
-            pklog.critical("no activity for %s time sending ctrl-c" \
-                           % self.timeout)
-            os.write(self.master_fd, chr(3))
-            #FIXME: include this into the normal install progress and add 
-            #       correct package information
-            raise InstallTimeOutPKError(self.output)
-
-    def conffile(self, current, new):
-        pklog.warning("Config file prompt: '%s' (sending no)" % current)
-        self.conffile_prompts.add(new)
-
-    def error(self, pkg, msg):
-        raise PackageManagerFailedPKError(pkg, msg, self.output)
-
-    def finishUpdate(self):
-        pklog.debug("finishUpdate()")
-        if self.conffile_prompts:
-            self._backend.Message(MESSAGE_CONFIG_FILES_CHANGED, 
-                                  "The following conffile prompts were found "
-                                  "and need investiagtion: %s" % \
-                                  "\n".join(self.conffile_prompts))
-        # Check for required restarts
-        if os.path.exists("/var/run/reboot-required") and \
-           os.path.getmtime("/var/run/reboot-required") > self.start_time:
-            self._backend.RequireRestart(RESTART_SYSTEM, "")
-
-
-class PackageKitDpkgInstallProgress(DpkgInstallProgress,
-                                    PackageKitInstallProgress):
-    """
-    Class to integrate the progress of core dpkg operations into PackageKit
-    """
-    def run(self, filenames):
-        return DpkgInstallProgress.run(self, filenames)
-
-    def updateInterface(self):
-        DpkgInstallProgress.updateInterface(self)
-        try:
-            out = os.read(self.master_fd, 512)
-            self.output += out
-            if out != "": pklog.debug("Dpkg out: %s" % out)
-        except OSError:
-            pass
-        # we timed out, send ctrl-c
-        if self.last_activity + self.timeout < time.time():
-            pklog.critical("no activity for %s time sending "
-                           "ctrl-c" % self.timeout)
-            os.write(self.master_fd, chr(3))
-            raise InstallTimeOutPKError(self.output)
-
-
-if REPOS_SUPPORT == True:
-    class PackageKitSoftwareProperties(softwareproperties.SoftwareProperties.SoftwareProperties):
-        """
-        Helper class to fix a siily bug in python-software-properties
-        """
-        def set_modified_sourceslist(self):
-            self.save_sourceslist()
-
-
-class PackageKitAptBackend(PackageKitBaseBackend):
-    '''
-    PackageKit backend for apt
-    '''
-    def __init__(self, bus_name, dbus_path):
-        pklog.info("Initializing APT backend")
-        signal.signal(signal.SIGQUIT, sigquit)
-        self._cache = None
-        self._canceled = threading.Event()
-        self._canceled.clear()
-        self._lock = threading.Lock()
-        self._last_cache_refresh = None
-        PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
-
-    # Methods ( client -> engine -> backend )
-
-    def doInit(self):
-        pklog.info("Initializing cache")
-        self.StatusChanged(STATUS_RUNNING)
-        self.AllowCancel(False)
-        self.NoPercentageUpdates()
-        self._open_cache(progress=False)
-
-    @serialize
-    def doExit(self):
-        gobject.idle_add(self._doExitDelay)
-
-    def doCancel(self):
-        pklog.info("Canceling current action")
-        self.StatusChanged(STATUS_CANCEL)
-        self._canceled.set()
-        self._canceled.wait()
-
-    @serialize
-    @threaded
-    def doSearchFile(self, filters, filename):
-        '''
-        Implement the apt2-search-file functionality
-
-        Apt specific: Works only for installed files. Since config files are
-        not removed by default even not installed packages can be reported.
-        '''
-        pklog.info("Searching for file: %s" % filename)
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(True)
-
-        for pkg in self._cache:
-            if self._check_canceled(): return False
-            for installed_file in self._get_installed_files(pkg):
-                if filename in installed_file:
-                    self._emit_visible_package(filters, pkg)
-                    break
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doSearchGroup(self, filters, group):
-        '''
-        Implement the apt2-search-group functionality
-        '''
-        pklog.info("Searching for group: %s" % group)
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(True)
-
-        for pkg in self._cache:
-            if self._check_canceled(): return False
-            elif self._get_package_group(pkg) == group:
-                self._emit_visible_package(filters, pkg)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doSearchName(self, filters, search):
-        '''
-        Implement the apt2-search-name functionality
-        '''
-        pklog.info("Searching for package name: %s" % search)
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(True)
-
-        for pkg in self._cache:
-            if self._check_canceled(): return False
-            elif search in pkg.name:
-                self._emit_visible_package(filters, pkg)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doSearchDetails(self, filters, search):
-        '''
-        Implement the apt2-search-details functionality
-        '''
-        pklog.info("Searching for package name: %s" % search)
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(True)
-        results = []
-
-        if XAPIAN_SUPPORT == True:
-            search_flags = (xapian.QueryParser.FLAG_BOOLEAN |
-                            xapian.QueryParser.FLAG_PHRASE |
-                            xapian.QueryParser.FLAG_LOVEHATE |
-                            xapian.QueryParser.FLAG_BOOLEAN_ANY_CASE)
-            pklog.debug("Performing xapian db based search")
-            db = xapian.Database(XAPIAN_DB)
-            parser = xapian.QueryParser()
-            query = parser.parse_query(unicode(search),
-                                       search_flags)
-            enquire = xapian.Enquire(db)
-            enquire.set_query(query)
-            matches = enquire.get_mset(0, 1000)
-            for r in  map(lambda m: m[xapian.MSET_DOCUMENT].get_data(),
-                          enquire.get_mset(0,1000)):
-                if self._cache.has_key(r):
-                    results.append(self._cache[r])
-        else:
-            pklog.debug("Performing apt cache based search")
-            for p in self._cache._dict.values():
-                if self._check_canceled(): return
-                needle = search.strip().lower()
-                haystack = p.description.lower()
-                if p.name.find(needle) >= 0 or haystack.find(needle) >= 0:
-                    results.append(p)
-
-        for r in results:
-            if self._check_canceled(): return
-            self._emit_visible_package(filters, r)
-
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetDistroUpgrades(self):
-        '''
-        Implement the {backend}-get-distro-upgrades functionality
-        '''
-        pklog.info("Get distro upgrades")
-        self.StatusChanged(STATUS_INFO)
-        self.AllowCancel(False)
-        self.NoPercentageUpdates()
-
-        if META_RELEASE_SUPPORT == False:
-            if self._cache.has_key("update-manager-core") and \
-               self._cache["update-manager-core"].isInstalled == False:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "Please install the package update-manager-core to get notified "
-                               "of the latest distribution releases.")
-            else:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "Please make sure that update-manager-core is"
-                               "correctly installed.")
-            self.Finished(EXIT_FAILED)
-            return
-
-        #FIXME Evil to start the download during init
-        meta_release = MetaReleaseCore(False, False)
-        #FIXME: should use a lock
-        while meta_release.downloading:
-            time.sleep(1)
-        #FIXME: Add support for description
-        if meta_release.new_dist != None:
-            self.DistroUpgrade("stable", 
-                               "%s %s" % (meta_release.new_dist.name,
-                                          meta_release.new_dist.version),
-                               "The latest stable release")
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetUpdates(self, filters):
-        '''
-        Implement the {backend}-get-update functionality
-        '''
-        def succeeds_security_update(pkg):
-            """
-            Return True if an update succeeds a previous security update
-
-            An example would be a package with version 1.1 in the security
-            archive and 1.1.1 in the archive of proposed updates or the
-            same version in both archives.
-            """
-            inst_ver = pkg._pkg.CurrentVer
-            for ver in pkg._pkg.VersionList:
-                # Skip versions which are not later
-                if inst_ver and \
-                   apt_pkg.VersionCompare(ver.VerStr, inst_ver.VerStr) <= 0:
-                    continue
-                for(verFileIter, index) in ver.FileList:
-                    if verFileIter.Origin in ["Debian", "Ubuntu"] and \
-                       (verFileIter.Archive.endswith("-security") or \
-                        verFileIter.Label == "Debian-Security"):
-                        indexfile = pkg._list.FindIndex(verFileIter)
-                        if indexfile and indexfile.IsTrusted:
-                            return True
-            return False
-        #FIXME: Implment the basename filter
-        pklog.info("Get updates")
-        self.StatusChanged(STATUS_QUERY)
-        self.AllowCancel(True)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self._cache.upgrade(False)
-        updates = filter(lambda p: self._cache[p].isUpgradable,
-                         self._cache.keys())
-        for pkg in self._cache.getChanges():
-            if self._check_canceled(): return False
-            else:
-                updates.remove(pkg.name)
-                info = INFO_NORMAL
-                archive = pkg.candidateOrigin[0].archive
-                origin = pkg.candidateOrigin[0].origin
-                trusted = pkg.candidateOrigin[0].trusted
-                label = pkg.candidateOrigin[0].label
-                if origin in ["Debian", "Ubuntu"] and trusted == True:
-                    if archive.endswith("-security") or \
-                       label == "Debian-Security":
-                        info = INFO_SECURITY
-                    elif succeeds_security_update(pkg):
-                        pklog.debug("Update of %s succeeds a security "
-                                    "update. Raising its priority." % pkg.name)
-                        info = INFO_SECURITY
-                    elif archive.endswith("-backports"):
-                        info = INFO_ENHANCEMENT
-                    elif archive.endswith("-updates"):
-                        info = INFO_BUGFIX
-                if origin in ["Backports.org archive"] and trusted == True:
-                    info = INFO_ENHANCEMENT
-                self._emit_package(pkg, info, force_candidate=True)
-        # Report packages that are upgradable but cannot be upgraded
-        for missed in updates:
-            self._emit_package(self._cache[missed], INFO_BLOCKED)
-        self._cache.clear()
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetUpdateDetail(self, pkg_ids):
-        '''
-        Implement the {backend}-get-update-details functionality
-        '''
-        def get_bug_urls(changelog):
-            """
-            Create a list of urls pointing to closed bugs in the changelog
-            """
-            urls = []
-            #FIXME: Add support for Launchpad/Ubuntu
-            for r in re.findall(MATCH_BUG_CLOSES_DEBIAN, changelog,
-                                re.IGNORECASE | re.MULTILINE):
-                urls.extend(map(lambda b: HREF_BUG_DEBIAN % b,
-                                re.findall(MATCH_BUG_NUMBERS, r)))
-            return urls
-
-        def get_cve_urls(changelog):
-            """
-            Create a list of urls pointing to cves referred in the changelog
-            """
-            return map(lambda c: HREF_CVE % c,
-                       re.findall(MATCH_CVE, changelog, re.MULTILINE))
-
-        pklog.info("Get update details of %s" % pkg_ids)
-        self.StatusChanged(STATUS_INFO)
-        self.NoPercentageUpdates()
-        self.AllowCancel(True)
-        self._check_init(progress=False)
-        for pkg_id in pkg_ids:
-            if self._check_canceled(): return
-            pkg = self._find_package_by_id(pkg_id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s isn't available" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            # FIXME add some real data
-            updates = self.get_id_from_package(pkg, force_candidate=False)
-            obsoletes = ""
-            vendor_url = ""
-            restart = ""
-            update_text = ""
-            state = ""
-            issued = ""
-            updated = ""
-            #FIXME: Replace this method with the python-apt one as soon as the
-            #       consolidate branch gets merged
-            self.StatusChanged(STATUS_DOWNLOAD_CHANGELOG)
-            changelog = self._get_changelog(pkg)
-            self.StatusChanged(STATUS_INFO)
-            bugzilla_url = ";".join(get_bug_urls(changelog))
-            cve_url = ";".join(get_cve_urls(changelog))
-            self.UpdateDetail(pkg_id, updates, obsoletes, vendor_url,
-                              bugzilla_url, cve_url, restart, update_text,
-                              changelog, state, issued, updated)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetDetails(self, pkg_ids):
-        '''
-        Implement the {backend}-get-details functionality
-        '''
-        pklog.info("Get details of %s" % pkg_ids)
-        self.StatusChanged(STATUS_DEP_RESOLVE)
-        self.NoPercentageUpdates()
-        self.AllowCancel(True)
-        self._check_init(progress=False)
-        for pkg_id in pkg_ids:
-            if self._check_canceled(): return
-            pkg = self._find_package_by_id(pkg_id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s isn't available" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            desc = self._get_package_description(pkg)
-            #FIXME: We need more fine grained license information!
-            candidate = pkg.candidateOrigin
-            if candidate != None and  \
-               candidate[0].component in ["main", "universe"] and \
-               candidate[0].origin in ["Debian", "Ubuntu"]:
-                license = "free"
-            else:
-                license = "unknown"
-            group = self._get_package_group(pkg)
-            self.Details(pkg_id, license, group, desc,
-                         pkg.homepage, pkg.packageSize)
-            self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    @unlock_cache_afterwards
-    def doUpdateSystem(self):
-        '''
-        Implement the {backend}-update-system functionality
-        '''
-        pklog.info("Upgrading system")
-        if not self._lock_cache(): return
-        self.StatusChanged(STATUS_UPDATE)
-        self.AllowCancel(False)
-        self.PercentageChanged(0)
-        self._check_init(prange=(0,5))
-        try:
-            self._cache.upgrade(distUpgrade=False)
-        except:
-            self._cache.clear()
-            self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
-                           "Failed to upgrade the system.")
-            self.Finished(EXIT_FAILED)
-            return
-        if not self._commit_changes(): return False
-        self.PercentageChanged(100)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    @unlock_cache_afterwards
-    def doRemovePackages(self, ids, deps=True, auto=False):
-        '''
-        Implement the {backend}-remove functionality
-        '''
-        pklog.info("Removing package(s): id %s" % ids)
-        if not self._lock_cache(): return
-        self.StatusChanged(STATUS_REMOVE)
-        self.AllowCancel(False)
-        self.PercentageChanged(0)
-        self._check_init(prange=(0,10))
-        pkgs=[]
-        for id in ids:
-            pkg = self._find_package_by_id(id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s isn't available" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            if not pkg.isInstalled:
-                self.ErrorCode(ERROR_PACKAGE_NOT_INSTALLED,
-                               "Package %s isn't installed" % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-            pkgs.append(pkg.name[:])
-            if pkg._pkg.Essential == True:
-                self.ErrorCode(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE,
-                               "Package %s cannot be removed." % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-            try:
-                pkg.markDelete()
-            except:
-                self._open_cache(prange=(90,99))
-                self.ErrorCode(ERROR_UNKNOWN, "Removal of %s failed" % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-        if not self._commit_changes(fetch_range=(10,10),
-                                    install_range=(10,90)):
-            return False
-        self._open_cache(prange=(90,99))
-        for p in pkgs:
-            if self._cache.has_key(p) and self._cache[p].isInstalled:
-                self.ErrorCode(ERROR_UNKNOWN, "%s is still installed" % p)
-                self.Finished(EXIT_FAILED)
-                return
-        self.PercentageChanged(100)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetRepoList(self, filters):
-        '''
-        Implement the {backend}-get-repo-list functionality
-
-        FIXME: should we use the abstration of software-properties or provide
-               low level access using pure aptsources?
-        '''
-        pklog.info("Getting repository list: %s" % filters)
-        self.StatusChanged(STATUS_INFO)
-        self.AllowCancel(False)
-        self.PercentageChanged(0)
-        if REPOS_SUPPORT == False:
-            if self._cache.has_key("python-software-properties") and \
-               self._cache["python-software-properties"].isInstalled == False:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "Please install the package "
-                               "python-software-properties to handle repositories")
-            else:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "Please make sure that python-software-properties is"
-                               "correctly installed.")
-            self.Finished(EXIT_FAILED)
-            return
-        filter_list = filters.split(";")
-        repos = PackageKitSoftwareProperties()
-        # Emit distro components as virtual repositories
-        for comp in repos.distro.source_template.components:
-            repo_id = "%s_comp_%s" % (repos.distro.id, comp.name)
-            description = "%s %s - %s (%s)" % (repos.distro.id,
-                                               repos.distro.release,
-                                               comp.get_description(),
-                                               comp.name)
-            #FIXME: There is no inconsitent state in PackageKit
-            enabled = repos.get_comp_download_state(comp)[0]
-            if not FILTER_DEVELOPMENT in filter_list:
-                self.RepoDetail(repo_id, description, enabled)
-        # Emit distro's virtual update repositories
-        for template in repos.distro.source_template.children:
-            repo_id = "%s_child_%s" % (repos.distro.id, template.name)
-            description = "%s %s - %s (%s)" % (repos.distro.id,
-                                               repos.distro.release,
-                                               template.description,
-                                               template.name)
-            #FIXME: There is no inconsitent state in PackageKit
-            enabled = repos.get_comp_child_state(template)[0]
-            if not FILTER_DEVELOPMENT in filter_list:
-                self.RepoDetail(repo_id, description, enabled)
-        # Emit distro's cdrom sources
-        for source in repos.get_cdrom_sources():
-            if FILTER_NOT_DEVELOPMENT in filter_list and \
-               source.type in ("deb-src", "rpm-src"):
-                continue
-            enabled = not source.disabled
-            # Remove markups from the description
-            description = re.sub(r"</?b>", "", repos.render_source(source))
-            repo_id = "cdrom_%s_%s" % (source.uri, source.dist)
-            repo_id.join(map(lambda c: "_%s" % c, source.comps))
-            self.RepoDetail(repo_id, description, enabled)
-        # Emit distro's virtual source code repositoriy
-        if not FILTER_NOT_DEVELOPMENT in filter_list:
-            repo_id = "%s_source" % repos.distro.id
-            enabled = repos.get_source_code_state() or False
-            #FIXME: no translation :(
-            description = "%s %s - Source code" % (repos.distro.id, 
-                                                   repos.distro.release)
-            self.RepoDetail(repo_id, description, enabled)
-        # Emit third party repositories
-        for source in repos.get_isv_sources():
-            if FILTER_NOT_DEVELOPMENT in filter_list and \
-               source.type in ("deb-src", "rpm-src"):
-                continue
-            enabled = not source.disabled
-            # Remove markups from the description
-            description = re.sub(r"</?b>", "", repos.render_source(source))
-            repo_id = "isv_%s_%s" % (source.uri, source.dist)
-            repo_id.join(map(lambda c: "_%s" % c, source.comps))
-            self.RepoDetail(repo_id, description, enabled)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doRepoEnable(self, repo_id, enable):
-        '''
-        Implement the {backend}-repo-enable functionality
-
-        FIXME: should we use the abstration of software-properties or provide
-               low level access using pure aptsources?
-        '''
-        pklog.info("Enabling repository: %s %s" % (repo_id, enable))
-        self.StatusChanged(STATUS_RUNNING)
-        self.AllowCancel(False)
-        self.PercentageChanged(0)
-        if REPOS_SUPPORT == False:
-            if self._cache.has_key("python-software-properties") and \
-               self._cache["python-software-properties"].isInstalled == False:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "Please install the package "
-                               "python-software-properties to handle repositories")
-            else:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "Please make sure that python-software-properties is"
-                               "correctly installed.")
-            self.Finished(EXIT_FAILED)
-            return
-        repos = PackageKitSoftwareProperties()
-
-        found = False
-        # Check if the repo_id matches a distro component, e.g. main
-        if repo_id.startswith("%s_comp_" % repos.distro.id):
-            for comp in repos.distro.source_template.components:
-                if repo_id == "%s_comp_%s" % (repos.distro.id, comp.name):
-                    if enable == repos.get_comp_download_state(comp)[0]:
-                        pklog.debug("Repository is already enabled")
-                        pass
-                    if enable == True:
-                        repos.enable_component(comp.name)
-                    else:
-                        repos.disable_component(comp.name)
-                    found = True
-                    break
-        # Check if the repo_id matches a distro child repository, e.g. hardy-updates
-        elif repo_id.startswith("%s_child_" % repos.distro.id):
-            for template in repos.distro.source_template.children:
-                if repo_id == "%s_child_%s" % (repos.distro.id, template.name):
-                    if enable == repos.get_comp_child_state(template)[0]:
-                        pklog.debug("Repository is already enabled")
-                        pass
-                    elif enable == True:
-                        repos.enable_child_source(template)
-                    else:
-                        repos.disable_child_source(template)
-                    found = True
-                    break
-        # Check if the repo_id matches a cdrom repository
-        elif repo_id.startswith("cdrom_"):
-            for source in repos.get_isv_sources():
-                source_id = "cdrom_%s_%s" % (source.uri, source.dist)
-                source_id.join(map(lambda c: "_%s" % c, source.comps))
-                if repo_id == source_id:
-                    if source.disabled == enable:
-                        source.disabled = not enable
-                        repos.save_sourceslist()
-                    else:
-                        pklog.debug("Repository is already enabled")
-                    found = True
-                    break
-        # Check if the repo_id matches an isv repository
-        elif repo_id.startswith("isv_"):
-            for source in repos.get_isv_sources():
-                source_id = "isv_%s_%s" % (source.uri, source.dist)
-                source_id.join(map(lambda c: "_%s" % c, source.comps))
-                if repo_id == source_id:
-                    if source.disabled == enable:
-                        source.disabled = not enable
-                        repos.save_sourceslist()
-                    else:
-                        pklog.debug("Repository is already enabled")
-                    found = True
-                    break
-        if found == False:
-            self.ErrorCode(ERROR_REPO_NOT_AVAILABLE,
-                           "The repository of the id %s isn't available" % repo_id)
-            self.Finished(EXIT_FAILED)
-            return
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    @unlock_cache_afterwards
-    def doUpdatePackages(self, ids):
-        '''
-        Implement the {backend}-update functionality
-        '''
-        pklog.info("Updating package with id %s" % ids)
-        if not self._lock_cache(): return
-        self.StatusChanged(STATUS_UPDATE)
-        self.AllowCancel(False)
-        self.PercentageChanged(0)
-        self._check_init(prange=(0,10))
-        pkgs=[]
-        for id in ids:
-            pkg = self._find_package_by_id(id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s isn't available" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            if not pkg.isUpgradable:
-                self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,
-                               "Package %s is already up-to-date" % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-            pkgs.append(pkg.name[:])
-            try:
-                pkg.markUpgrade()
-            except:
-                self._open_cache(prange=(90,100))
-                self.ErrorCode(ERROR_UNKNOWN, "%s could not be queued for "
-                                              "update" % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-        if not self._commit_changes(): return False
-        self._open_cache(prange=(90,100))
-        self.PercentageChanged(100)
-        pklog.debug("Checking success of operation")
-        for p in pkgs:
-            if not self._cache.has_key(p) or not self._cache[p].isInstalled \
-               or self._cache[p].isUpgradable:
-                self.ErrorCode(ERROR_UNKNOWN, "%s was not updated" % p)
-                self.Finished(EXIT_FAILED)
-                return
-        pklog.debug("Sending success signal")
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doDownloadPackages(self, ids, dest):
-        '''
-        Implement the {backend}-download-packages functionality
-        '''
-        pklog.info("Downloading packages: %s" % ids)
-        self.StatusChanged(STATUS_DOWNLOAD)
-        self.AllowCancel(True)
-        self.PercentageChanged(0)
-        # Check the destination directory
-        if not os.path.isdir(dest) or not os.access(dest, os.W_OK):
-            self.ErrorCode(ERROR_UNKNOWN,
-                           "The directory '%s' is not writable" % dest)
-            self.Finished(EXIT_FAILED)
-            return
-        # Setup the fetcher
-        self._check_init(prange=(0,10))
-        progress = PackageKitFetchProgress(self, prange=(10,90))
-        fetcher = apt_pkg.GetAcquire(progress)
-        pm = apt_pkg.GetPackageManager(self._cache._depcache)
-        recs = apt_pkg.GetPkgRecords(self._cache._cache)
-        list = apt_pkg.GetPkgSourceList()
-        list.ReadMainList()
-        # Mark installed packages for reinstallation and not installed packages
-        # for installation without dependencies
-        for id in ids:
-            if self._check_canceled(): return
-            pkg = self._find_package_by_id(id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "There is no package %s" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            if pkg.isInstalled:
-                self._cache._depcache.SetReInstall(pkg._pkg, True)
-            else:
-                self._cache._depcache.MarkInstall(pkg._pkg, False)
-        # Download 
-        pm.GetArchives(fetcher, list, recs)
-        res = fetcher.Run()
-        self._cache.clear()
-        self.PercentageChanged(95)
-        # Copy files from cache to final destination
-        for item in fetcher.Items:
-            if self._check_canceled(): return
-            pklog.debug("Download item: %s" % item)
-            if (item.Status != item.StatDone and not item.StatIdle) or \
-                res == fetcher.ResultCancelled:
-                self.ErrorCode(ERROR_PACKAGE_DOWNLOAD_FAILED,
-                               "Failed to download %s" % item.DescURI)
-                self.Finished(EXIT_FAILED)
-                return
-            pklog.debug("Copying %s to %s ..." % (item.DestFile, dest))
-            try:
-                shutil.copy(item.DestFile, dest)
-            except Exception, e:
-                self.ErrorCode(ERROR_INTERNAL_ERROR,
-                               "Failed to copy %s to %s: %s" % (item.DestFile,
-                                                                dest, e))
-                self.Finished(EXIT_FAILED)
-                return
-        self.PercentageChanged(100)
-        pklog.debug("Sending success signal")
-        self.Finished(EXIT_SUCCESS)
- 
-    @serialize
-    @threaded
-    @unlock_cache_afterwards
-    def doInstallPackages(self, ids):
-        '''
-        Implement the {backend}-install functionality
-        '''
-        pklog.info("Installing package with id %s" % ids)
-        if not self._lock_cache(): return
-        self.StatusChanged(STATUS_INSTALL)
-        self.AllowCancel(False)
-        self.PercentageChanged(0)
-        self._check_init(prange=(0,10))
-        pkgs=[]
-        for id in ids:
-            pkg = self._find_package_by_id(id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s isn't available" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            if pkg.isInstalled:
-                self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,
-                               "Package %s is already installed" % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-            pkgs.append(pkg.name[:])
-            try:
-                pkg.markInstall()
-            except Exception, e:
-                self._open_cache(prange=(90,100))
-                self.ErrorCode(ERROR_UNKNOWN, "%s could not be queued for "
-                                              "installation: %s" % (pkg.name,e))
-                self.Finished(EXIT_FAILED)
-                return
-        if not self._commit_changes(): return False
-        self._open_cache(prange=(90,100))
-        self.PercentageChanged(100)
-        pklog.debug("Checking success of operation")
-        for p in pkgs:
-            if not self._cache.has_key(p) or not self._cache[p].isInstalled:
-                self.ErrorCode(ERROR_UNKNOWN, "%s was not installed" % p)
-                self.Finished(EXIT_FAILED)
-                return
-        pklog.debug("Sending success signal")
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    @unlock_cache_afterwards
-    def doInstallFiles(self, trusted, full_paths):
-        '''
-        Implement install-files for the apt backend
-        Install local Debian package files
-        '''
-        pklog.info("Installing package files: %s" % full_paths)
-        if not self._lock_cache(): return
-        self.StatusChanged(STATUS_INSTALL)
-        self.AllowCancel(False)
-        self.PercentageChanged(0)
-        self._check_init(prange=(0,10))
-        packages = []
-        # Collect all dependencies which need to be installed
-        self.StatusChanged(STATUS_DEP_RESOLVE)
-        for path in full_paths:
-            deb = apt.debfile.DebPackage(path, self._cache)
-            packages.append(deb)
-            if not deb.check():
-                self.ErrorCode(ERROR_UNKNOWN, deb._failureString)
-                self.Finished(EXIT_FAILED)
-                return
-            (install, remove, unauthenticated) = deb.requiredChanges
-            pklog.debug("Changes: Install %s, Remove %s, Unauthenticated "
-                        "%s" % (install, remove, unauthenticated))
-            if len(remove) > 0:
-                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED, 
-                               "Remove the following packages "
-                               "before: %s" % remove)
-                self.Finished(EXIT_FAILED)
-                return
-            if deb.compare_to_version_in_cache() == \
-               apt.debfile.VERSION_OUTDATED:
-                self.Message(MESSAGE_NEWER_PACKAGE_EXISTS, 
-                             "There is a later version of %s "
-                             "available in the repositories." % deb.pkgname)
-        if len(self._cache.getChanges()) > 0 and not \
-           self._commit_changes((10,25), (25,50)): 
-            return False
-        # Install the Debian package files
-        d = PackageKitDpkgInstallProgress(self)
-        try:
-            d.startUpdate()
-            d.install(full_paths)
-            d.finishUpdate()
-        except InstallTimeOutPKError, e:
-            self._recover()
-            #FIXME: should provide more information
-            self.ErrorCode(ERROR_UNKNOWN,
-                           "Transaction was cancelled since the installation "
-                           "of a package hung.\n"
-                           "This can be caused by maintainer scripts which "
-                           "require input on the terminal:\n%s" % e.message)
-            self.Finished(EXIT_KILLED)
-            return
-        except PackageManagerFailedPKError, e:
-            self._recover()
-            self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
-            self.Finished(EXIT_FAILED)
-            return
-        except Exception, e:
-            self._recover()
-            self.ErrorCode(ERROR_INTERNAL_ERROR, e.message)
-            self.Finished(EXIT_FAILED)
-            return
-        self.PercentageChanged(100)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    @unlock_cache_afterwards
-    def doRefreshCache(self, force):
-        '''
-        Implement the {backend}-refresh_cache functionality
-        '''
-        pklog.info("Refresh cache")
-        if not self._lock_cache(): return
-        self.StatusChanged(STATUS_REFRESH_CACHE)
-        self.last_action_time = time.time()
-        self.AllowCancel(False);
-        self.PercentageChanged(0)
-        self._check_init((0,10))
-        try:
-            self._cache.update(PackageKitFetchProgress(self, prange=(10,95)))
-        except Exception, e:
-            self._open_cache(prange=(95,100))
-            if self._check_canceled(): return False
-            self.ErrorCode(ERROR_UNKNOWN, "Refreshing cache failed: %s" % e)
-            self.Finished(EXIT_FAILED)
-            return
-        self._open_cache(prange=(95,100))
-        self.PercentageChanged(100)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetPackages(self, filters):
-        '''
-        Implement the apt2-get-packages functionality
-        '''
-        pklog.info("Get all packages")
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(True)
-
-        for pkg in self._cache:
-            if self._check_canceled(): return False
-            elif self._is_package_visible(pkg, filters):
-                self._emit_package(pkg)
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doResolve(self, filters, names):
-        '''
-        Implement the apt2-resolve functionality
-        '''
-        pklog.info("Resolve")
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(False)
-
-        for name in names:
-            if self._cache.has_key(name):
-                self._emit_visible_package(filters, self._cache[name])
-            else:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package name %s could not be resolved" % name)
-                self.Finished(EXIT_FAILED)
-                return
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetDepends(self, filter, ids, recursive=False):
-        '''
-        Implement the apt2-get-depends functionality
-
-        Emit all packages that need to be installed or updated to install
-        the given package ids. It behaves like a preview of the changes
-        required for the installation. An error will be emitted if the 
-        dependecies cannot be satisfied.
-        In contrast to the yum backend the whole dependency resoltions is done 
-        by the package manager. Therefor the list of satisfied packages cannot
-        be computed easily. GDebi features this. Perhaps this should be moved
-        to python-apt.
-        '''
-        pklog.info("Get depends (%s,%s,%s)" % (filter, ids, recursive))
-        #FIXME: recursive is not yet implemented
-        if recursive == True:
-            pklog.warn("Recursive dependencies are not implemented")
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(True)
-
-        # Mark all packages for installation
-        pkgs = []
-        for id in ids:
-            if self._check_canceled(): return
-            pkg = self._find_package_by_id(id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s isn't available" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            try:
-                pkg.markInstall()
-            except Exception, e:
-                #FIXME: Introduce a new info enumerate PK_INFO_MISSING for
-                #       missing dependecies
-                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
-                               "Dependecies for %s cannot be satisfied: %s" % e)
-                self.Finished(EXIT_FAILED)
-                return
-            pkgs.append(pkg)
-        # Check the status of the resulting changes
-        for p in self._cache.getChanges():
-            if self._check_canceled(): return
-            if p in pkgs: continue
-            if p.markedDelete:
-                # Packagekit policy forbids removing packages for installation
-                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
-                               "Remove the package %s before" % p.name)
-                self.Finished(EXIT_FAILED)
-                return
-            elif p.markedInstall or p.markedUpgrade:
-                if self._is_package_visible(p, filter):
-                    self._emit_package(p)
-            else:
-                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
-                               "Please use an advanced package management tool "
-                               "e.g. Synaptic or aptitude, since there is a "
-                               "complex dependency situation.")
-                self.Finished(EXIT_FAILED)
-                return
-        # Clean up
-        self._cache.clear()
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetRequires(self, filter, ids, recursive=False):
-        '''
-        Implement the apt2-get-requires functionality
-        '''
-        pklog.info("Get requires (%s,%s,%s)" % (filter, ids, recursive))
-        #FIXME: recursive is not yet implemented
-        if recursive == True:
-            pklog.warn("Recursive dependencies are not implemented")
-        self.StatusChanged(STATUS_DEP_RESOLVE)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(True)
-        pkgs = []
-
-        # Mark all packages for installation
-        for id in ids:
-            if self._check_canceled(): return
-            pkg = self._find_package_by_id(id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s isn't available" % id)
-                self.Finished(EXIT_FAILED)
-                return
-            if pkg._pkg.Essential == True:
-                self.ErrorCode(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE,
-                               "Package %s cannot be removed." % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-            pkgs.append(pkg)
-            try:
-                pkg.markDelete()
-            except Exception, e:
-                #FIXME: Introduce a new info enumerate PK_INFO_MISSING for
-                #       missing dependecies
-                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
-                               "Error removing %s: %s" % (pkg.name, e))
-                self.Finished(EXIT_FAILED)
-                return
-        # Check the status of the resulting changes
-        for p in self._cache.getChanges():
-            if self._check_canceled(): return
-            if p.markedDelete:
-                if not p in pkgs and self._is_package_visible(p, filter):
-                    self._emit_package(p)
-            else:
-                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
-                               "Please use an advanced package management tool "
-                               "e.g. Synaptic or aptitude, since there is a "
-                               "complex dependency situation.")
-                self.Finished(EXIT_FAILED)
-                return
-        # Clean up
-        self._cache.clear()
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doWhatProvides(self, filters, provides_type, search):
-        def get_mapping_db(path):
-            """
-            Return the gdbm database at the given path or send an
-            appropriate error message
-            """
-            if not os.access(path, os.R_OK):
-                if self._cache.has_key("app-install-data") and \
-                   self._cache["app-install-data"].isInstalled == False:
-                    self.ErrorCode(ERROR_UNKNOWN,
-                                   "Please install the package "
-                                   "app-install data for a list of "
-                                   "applications that can handle files of "
-                                   "the given type")
-                else:
-                    self.ErrorCode(ERROR_UNKNOWN,
-                                   "The list of applications that can handle "
-                                   "files of the given type cannot be opened.\n"
-                                   "Try to reinstall the package "
-                                   "app-install-data.")
-                return None
-            try:
-                db = gdbm.open(path)
-            except:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "The list of applications that can handle "
-                               "files of the given type cannot be opened.\n"
-                               "Try to reinstall the package "
-                               "app-install-data.")
-                return None
-            else:
-                return db
-
-        self.StatusChanged(STATUS_QUERY)
-        self.NoPercentageUpdates()
-        self._check_init(progress=False)
-        self.AllowCancel(False)
-        if provides_type == PROVIDES_CODEC:
-            # The search term from the codec helper looks like this one:
-            match = re.match(r"gstreamer([0-9\.]+)\((.+?)\)", search)
-            if not match:
-                self.ErrorCode(ERROR_UNKNOWN,
-                               "The search term is invalid")
-                self.Finished(EXIT_FAILED)
-                return
-            codec = "%s:%s" % (match.group(1), match.group(2))
-            db = get_mapping_db("/var/cache/app-install/gai-codec-map.gdbm")
-            if db == None:
-                self.ErrorCode(ERROR_INTERNAL_ERROR,
-                               "Failed to open codec mapping database")
-                self.Finished(EXIT_FAILED)
-                return
-            if db.has_key(codec):
-                # The codec mapping db stores the packages as a string
-                # separated by spaces. Each package has its section
-                # prefixed and separated by a slash
-                # FIXME: Should make use of the section and emit a 
-                #        RepositoryRequired signal if the package does 
-                #        not exist
-                pkgs = map(lambda s: s.split("/")[1],
-                           db[codec].split(" "))
-                self._emit_visible_packages_by_name(filters, pkgs)
-        elif provides_type == PROVIDES_MIMETYPE:
-            # Emit packages that contain an application that can handle
-            # the given mime type
-            handlers = set()
-            db = get_mapping_db("/var/cache/app-install/gai-mime-map.gdbm")
-            if db == None:
-                self.Finished(EXIT_FAILED)
-                return
-            if db.has_key(search):
-                pklog.debug("Mime type is registered: %s" % db[search])
-                # The mime type handler db stores the packages as a string
-                # separated by spaces. Each package has its section
-                # prefixed and separated by a slash
-                # FIXME: Should make use of the section and emit a 
-                #        RepositoryRequired signal if the package does not exist
-                handlers = map(lambda s: s.split("/")[1],
-                               db[search].split(" "))
-                self._emit_visible_packages_by_name(filters, handlers)
-        else:
-            self.ErrorCode(ERROR_NOT_SUPPORTED,
-                           "This function is not implemented in this backend")
-            self.Finished(EXIT_FAILED)
-            return
-        self.Finished(EXIT_SUCCESS)
-
-    @serialize
-    @threaded
-    def doGetFiles(self, package_ids):
-        """
-        Emit the Files signal which includes the files included in a package
-        Apt only supports this for installed packages
-        """
-        self.StatusChanged(STATUS_INFO)
-        for id in package_ids:
-            pkg = self._find_package_by_id(id)
-            if pkg == None:
-                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
-                               "Package %s doesn't exist" % pkg.name)
-                self.Finished(EXIT_FAILED)
-                return
-            files = string.join(self._get_installed_files(pkg), ";")
-            self.Files(id, files)
-        self.Finished(EXIT_SUCCESS)
-
-    def doSetProxy(self, http_proxy, ftp_proxy):
-        '''
-        Set a proxy server for http and ftp transfer
-        '''
-        if http_proxy:
-            pklog.debug("Set http proxy to %s" % http_proxy)
-            apt_pkg.Config.set("http::Proxy", http_proxy)
-        if ftp_proxy:
-            pklog.debug("Set ftp proxy to %s" % ftp_proxy)
-            apt_pkg.Config.set("ftp::Proxy", ftp_proxy)
-
-    def doSetLocale(self, code):
-        '''
-        Set the locale of the daemon
-
-        '''
-        #FIXME: Needs testing
-        if code != "":
-            pklog.debug("Setting language to %s" % code)
-            locale.setlocale("LANG", code)
-
-    # Helpers
-
-    def _lock_cache(self):
-        """
-        Emit an error message and return true if the apt system lock cannot
-        be acquired.
-        """
-        try:
-            apt_pkg.PkgSystemLock()
-        except SystemError:
-            self.ErrorCode(ERROR_CANNOT_GET_LOCK,
-                           "Only use one package management programme at the "
-                           "the same time.")
-            self.Finished(EXIT_FAILED)
-            return False
-        return True
-
-    def _unlock_cache(self):
-        """
-        Unlock the system package cache
-        """
-        try:
-            apt_pkg.PkgSystemUnLock()
-        except SystemError:
-            return False
-        return True
-
-    def _open_cache(self, prange=(0,100), progress=True):
-        '''
-        (Re)Open the APT cache
-        '''
-        pklog.debug("Open APT cache")
-        self.StatusChanged(STATUS_LOADING_CACHE)
-        try:
-            self._cache = PackageKitCache(PackageKitOpProgress(self, prange,
-                                                               progress))
-        except:
-            self.ErrorCode(ERROR_NO_CACHE, "Package cache could not be opened")
-            self.Finished(EXIT_FAILED)
-            self.Exit()
-            return
-        if self._cache._depcache.BrokenCount > 0:
-            self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
-                           "There are broken dependecies on your system. "
-                           "Please use an advanced package manage e.g. "
-                           "Synaptic or aptitude to resolve this situation.")
-            self.Finished(EXIT_FAILED)
-            self.Exit()
-            return
-        self._last_cache_refresh = time.time()
-
-    def _recover(self, prange=(95,100)):
-        """
-        Try to recover from a package manager failure
-        """
-        self.StatusChanged(STATUS_CLEANUP)
-        self.NoPercentageUpdates()
-        try:
-            d = PackageKitDpkgInstallProgress(self)
-            d.startUpdate()
-            d.recover()
-            d.finishUpdate()
-        except:
-            pass
-        self._open_cache(prange)
-
-    def _commit_changes(self, fetch_range=(5,50), install_range=(50,90)):
-        """
-        Commit changes to the cache and handle errors
-        """
-        try:
-            self._cache.commit(PackageKitFetchProgress(self, fetch_range), 
-                               PackageKitInstallProgress(self, install_range))
-        except apt.cache.FetchFailedException, e:
-            self._open_cache(prange=(95,100))
-            self.ErrorCode(ERROR_PACKAGE_DOWNLOAD_FAILED, e.message)
-            self.Finished(EXIT_FAILED)
-        except apt.cache.FetchCancelledException:
-            self._open_cache(prange=(95,100))
-            self.Finished(EXIT_CANCELLED)
-            self._canceled.clear()
-        except InstallTimeOutPKError, e:
-            self._recover()
-            self._open_cache(prange=(95,100))
-            #FIXME: should provide more information
-            self.ErrorCode(ERROR_UNKNOWN,
-                           "Transaction was cancelled since the installation "
-                           "of a package hung.\n"
-                           "This can be caused by maintainer scripts which "
-                           "require input on the terminal:\n%s" % e.message)
-            self.Finished(EXIT_KILLED)
-        except PackageManagerFailedPKError, e:
-            self._recover()
-            self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
-            self.Finished(EXIT_FAILED)
-        else:
-            return True
-        return False
-
-    def _check_init(self, prange=(0,10), progress=True):
-        '''
-        Check if the backend was initialized well and try to recover from
-        a broken setup
-        '''
-        pklog.debug("Checking apt cache and xapian database")
-        pkg_cache = os.path.join(apt_pkg.Config["Dir"],
-                                 apt_pkg.Config["Dir::Cache"],
-                                 apt_pkg.Config["Dir::Cache::pkgcache"])
-        src_cache = os.path.join(apt_pkg.Config["Dir"],
-                                 apt_pkg.Config["Dir::Cache"],
-                                 apt_pkg.Config["Dir::Cache::srcpkgcache"])
-        # Check if the cache instance is of the coorect class type, contains
-        # any broken packages and if the dpkg status or apt cache files have 
-        # been changed since the last refresh
-        if not isinstance(self._cache, apt.cache.Cache) or \
-           (self._cache._depcache.BrokenCount > 0) or \
-           (os.stat(apt_pkg.Config["Dir::State::status"])[stat.ST_MTIME] > \
-            self._last_cache_refresh) or \
-           (os.stat(pkg_cache)[stat.ST_MTIME] > self._last_cache_refresh) or \
-           (os.stat(src_cache)[stat.ST_MTIME] > self._last_cache_refresh):
-            pklog.debug("Reloading the cache is required")
-            self._open_cache(prange, progress)
-        else:
-            self._cache.clear()
-
-    def _check_canceled(self):
-        '''
-        Check if the current transaction was canceled. If so send the
-        corresponding error message and return True
-        '''
-        if self._canceled.isSet():
-            self.Finished(EXIT_CANCELLED)
-            self._canceled.clear()
-            return True
-        return False
- 
-    def get_id_from_package(self, pkg, force_candidate=False):
-        '''
-        Return the packagekit id of package. By default this will be the 
-        installed version for installed packages and the candidate version
-        for not installed packages.
-
-        The force_candidate option will also report the id of the candidate
-        version for installed packages.
-        '''
-        origin = ""
-        cand_origin = pkg.candidateOrigin
-        if not pkg.isInstalled or force_candidate:
-            version = pkg.candidateVersion
-            if cand_origin:
-                origin = cand_origin[0].label
-        else:
-            version = pkg.installedVersion
-            if cand_origin and cand_origin[0].site != "" and \
-               pkg.installedVersion == pkg.candidateVersion:
-                origin = cand_origin[0].label
-        id = self._get_package_id(pkg.name, version, pkg.architecture, origin)
-        return id
-
-    def _emit_package(self, pkg, info=None, force_candidate=False):
-        '''
-        Send the Package signal for a given apt package
-        '''
-        id = self.get_id_from_package(pkg, force_candidate)
-        section = pkg.section.split("/")[-1]
-        if info == None:
-            if pkg.isInstalled:
-                if section == "metapackages":
-                    info = INFO_COLLECTION_INSTALLED
-                else:
-                    info = INFO_INSTALLED
-            else:
-                if section == "metapackages":
-                    info = INFO_COLLECTION_AVAILABLE
-                else:
-                    info = INFO_AVAILABLE
-        summary = pkg.summary
-        self.Package(info, id, summary)
-
-    def _emit_visible_package(self, filters, pkg, info=None):
-        """
-        Filter and emit a package
-        """
-        if self._is_package_visible(pkg, filters):
-            self._emit_package(pkg, info)
-
-    def _emit_visible_packages(self, filters, pkgs, info=None):
-        """
-        Filter and emit packages
-        """
-        for p in pkgs:
-            if self._is_package_visible(p, filters):
-                self._emit_package(p, info)
-
-    def _emit_visible_packages_by_name(self, filters, pkgs, info=None):
-        """
-        Find the packages with the given namens. Afterwards filter and emit
-        them
-        """
-        for name in pkgs:
-            if self._cache.has_key(name) and \
-               self._is_package_visible(self._cache[name], filters):
-                self._emit_package(self._cache[name], info)
-
-
-    def _is_package_visible(self, pkg, filters):
-        '''
-        Return True if the package should be shown in the user interface
-        '''
-        if filters == FILTER_NONE:
-            return True
-        for filter in filters.split(";"):
-            if (filter == FILTER_INSTALLED and not pkg.isInstalled) or \
-               (filter == FILTER_NOT_INSTALLED and pkg.isInstalled) or \
-               (filter == FILTER_SUPPORTED and not \
-                self._is_package_supported(pkg)) or \
-               (filter == FILTER_NOT_SUPPORTED and \
-                self._is_package_supported(pkg)) or \
-               (filter == FILTER_FREE and not self._is_package_free(pkg)) or \
-               (filter == FILTER_NOT_FREE and \
-                not self._is_package_not_free(pkg)) or \
-               (filter == FILTER_GUI and not self._has_package_gui(pkg)) or \
-               (filter == FILTER_NOT_GUI and self._has_package_gui(pkg)) or \
-               (filter == FILTER_COLLECTIONS and not \
-                self._is_package_collection(pkg)) or \
-               (filter == FILTER_NOT_COLLECTIONS and \
-                self._is_package_collection(pkg)) or\
-                (filter == FILTER_DEVELOPMENT and not \
-                self._is_package_devel(pkg)) or \
-               (filter == FILTER_NOT_DEVELOPMENT and \
-                self._is_package_devel(pkg)):
-                return False
-        return True
-
-    def _is_package_not_free(self, pkg):
-        """
-        Return True if we can be sure that the package's license isn't any 
-        free one
-        """
-        candidate = pkg.candidateOrigin
-        return candidate != None and \
-               ((candidate[0].origin == "Ubuntu" and \
-                 candidate[0].component in ["multiverse", "restricted"]) or \
-                (candidate[0].origin == "Debian" and \
-                 candidate[0].component in ["contrib", "non-free"])) and \
-               candidate[0].trusted == True
-
-    def _is_package_collection(self, pkg):
-        """
-        Return True if the package is a metapackge
-        """
-        section = pkg.section.split("/")[-1]
-        return section == "metapackages"
-
-    def _is_package_free(self, pkg):
-        """
-        Return True if we can be sure that the package has got a free license
-        """
-        candidate = pkg.candidateOrigin
-        return candidate != None and \
-               ((candidate[0].origin == "Ubuntu" and \
-                 candidate[0].component in ["main", "universe"]) or \
-                (candidate[0].origin == "Debian" and \
-                 candidate[0].component == "main")) and\
-               candidate[0].trusted == True
-
-    def _has_package_gui(self, pkg):
-        #FIXME: should go to a modified Package class
-        #FIXME: take application data into account. perhaps checking for
-        #       property in the xapian database
-        return pkg.section.split('/')[-1].lower() in ['x11', 'gnome', 'kde']
-
-    def _is_package_devel(self, pkg):
-        #FIXME: should go to a modified Package class
-        return pkg.name.endswith("-dev") or pkg.name.endswith("-dbg") or \
-               pkg.section.split('/')[-1].lower() in ['devel', 'libdevel']
-
-    def _is_package_supported(self, pkg):
-        candidate = pkg.candidateOrigin[0]
-        return candidate != None and \
-               candidate[0].origin == "Ubuntu" and \
-               candidate[0].component in ["main", "restricted"] and \
-               candidate[0].trusted == True
-
-    def _find_package_by_id(self, id):
-        '''
-        Return a package matching to the given package id
-        '''
-        # FIXME: Perform more checks
-        name, version, arch, data = self.get_package_from_id(id)
-        if self._cache.has_key(name):
-            return self._cache[name]
-        else:
-            return None
-
-    def _get_installed_files(self, pkg):
-        """
-        Return the list of unicode names of the files which have
-        been installed by the package
-
-        This method should be obsolete by the apt.package.Package.installedFiles
-        attribute as soon as the consolidate branch of python-apt gets merged
-        """
-        path = os.path.join(apt_pkg.Config["Dir"],
-                            "var/lib/dpkg/info/%s.list" % pkg.name)
-        try:
-            list = open(path)
-            files = list.read().decode().split("\n")
-            list.close()
-        except:
-            return []
-        return files
-
-    def _get_changelog(self, pkg, uri=None, cancel_lock=None):
-        """
-        Download the changelog of the package and return it as unicode 
-        string
-
-        This method is already part of the consolidate branch of python-apt
-
-        uri: Is the uri to the changelog file. The following named variables
-             will be substituted: src_section, prefix, src_pkg and src_ver
-             For example the Ubuntu changelog:
-             uri = "http://changelogs.ubuntu.com/changelogs/pool" \\
-                   "/%(src_section)s/%(prefix)s/%(src_pkg)s" \\
-                   "/%(src_pkg)s_%(src_ver)s/changelog"
-        cancel_lock: If this threading.Lock() is set, the download will be
-                     canceled
-        """
-        if uri == None:
-            if pkg.candidateOrigin[0].origin == "Debian":
-                uri = "http://packages.debian.org/changelogs/pool" \
-                      "/%(src_section)s/%(prefix)s/%(src_pkg)s" \
-                      "/%(src_pkg)s_%(src_ver)s/changelog"
-            elif pkg.candidateOrigin[0].origin == "Ubuntu":
-                uri = "http://changelogs.ubuntu.com/changelogs/pool" \
-                      "/%(src_section)s/%(prefix)s/%(src_pkg)s" \
-                      "/%(src_pkg)s_%(src_ver)s/changelog"
-            else:
-                return "The list of changes is not available"
-
-        # get the src package name
-        src_pkg = pkg.sourcePackageName
-
-        # assume "main" section 
-        src_section = "main"
-        # use the section of the candidate as a starting point
-        section = pkg._depcache.GetCandidateVer(pkg._pkg).Section
-
-        # get the source version, start with the binaries version
-        bin_ver = pkg.candidateVersion
-        src_ver = pkg.candidateVersion
-        #print "bin: %s" % binver
-        try:
-            # try to get the source version of the pkg, this differs
-            # for some (e.g. libnspr4 on ubuntu)
-            # this feature only works if the correct deb-src are in the 
-            # sources.list
-            # otherwise we fall back to the binary version number
-            src_records = apt_pkg.GetPkgSrcRecords()
-            src_rec = src_records.Lookup(src_pkg)
-            if src_rec:
-                src_ver = src_records.Version
-                #if apt_pkg.VersionCompare(binver, srcver) > 0:
-                #    srcver = binver
-                if not src_ver:
-                    src_ver = bin_ver
-                #print "srcver: %s" % src_ver
-                section = src_records.Section
-                #print "srcsect: %s" % section
-            else:
-                # fail into the error handler
-                raise SystemError
-        except SystemError, e:
-            src_ver = bin_ver
-
-        l = section.split("/")
-        if len(l) > 1:
-            src_section = l[0]
-
-        # lib is handled special
-        prefix = src_pkg[0]
-        if src_pkg.startswith("lib"):
-            prefix = "lib" + src_pkg[3]
-
-        # stip epoch
-        l = src_ver.split(":")
-        if len(l) > 1:
-            src_ver = "".join(l[1:])
-
-        uri = uri % {"src_section" : src_section,
-                     "prefix" : prefix,
-                     "src_pkg" : src_pkg,
-                     "src_ver" : src_ver}
-        try:
-            # Check if the download was canceled
-            if cancel_lock and cancel_lock.isSet(): return ""
-            changelog_file = urllib2.urlopen(uri)
-            # do only get the lines that are new
-            changelog = ""
-            regexp = "^%s \((.*)\)(.*)$" % (re.escape(src_pkg))
-
-            i=0
-            while True:
-                # Check if the download was canceled
-                if cancel_lock and cancel_lock.isSet(): return ""
-                # Read changelog line by line
-                line_raw = changelog_file.readline()
-                if line_raw == "":
-                    break
-                # The changelog is encoded in utf-8, but since there isn't any
-                # http header, urllib2 seems to treat it as ascii
-                line = line_raw.decode("utf-8")
-
-                #print line.encode('utf-8')
-                match = re.match(regexp, line)
-                if match:
-                    # strip epoch from installed version
-                    # and from changelog too
-                    installed = pkg.installedVersion
-                    if installed and ":" in installed:
-                        installed = installed.split(":",1)[1]
-                    changelog_ver = match.group(1)
-                    if changelog_ver and ":" in changelog_ver:
-                        changelog_ver = changelog_ver.split(":", 1)[1]
-                    if installed and \
-                        apt_pkg.VersionCompare(changelog_ver, installed) <= 0:
-                        break
-                # EOF (shouldn't really happen)
-                changelog += line
-
-            # Print an error if we failed to extract a changelog
-            if len(changelog) == 0:
-                changelog = "The list of changes is not available"
-        except urllib2.HTTPError,e:
-            return "The list of changes is not available yet.\n\n" \
-                    "Please use http://launchpad.net/ubuntu/+source/%s/%s/" \
-                    "+changelog\n" \
-                    "until the changes become available or try again " \
-                    "later." % (src_pkg, src_ver)
-        except IOError, httplib.BadStatusLine:
-            return "Failed to download the list of changes.\nPlease " \
-                   "check your Internet connection."
-        return changelog
-
-    def _get_package_group(self, pkg):
-        """
-        Return the packagekit group corresponding to the package's section
-        """
-        section = pkg.section.split("/")[-1]
-        if SECTION_GROUP_MAP.has_key(section):
-            return SECTION_GROUP_MAP[section]
-        else:
-            pklog.debug("Unkown package section %s of %s" % (pkg.section,
-                                                             pkg.name))
-            return GROUP_UNKNOWN
-
-    def _get_package_description(self, pkg):
-        """
-        Return the formated long description according to the Debian policy
-        (Chapter 5.6.13).
-        See http://www.debian.org/doc/debian-policy/ch-controlfields.html
-        for more information.
-        """
-        if not pkg._lookupRecord():
-            return ""
-        # get the translated description
-        ver = pkg._depcache.GetCandidateVer(pkg._pkg)
-        desc_iter = ver.TranslatedDescription
-        pkg._records.Lookup(desc_iter.FileList.pop(0))
-        desc = ""
-        try:
-            s = unicode(pkg._records.LongDesc,"utf-8")
-        except UnicodeDecodeError,e:
-            s = "Invalid unicode in description for '%s' (%s)" % (pkg.name, e)
-        lines = string.split(s, "\n")
-        for i in range(len(lines)):
-            # Skip the first line, since its a duplication of the summary
-            if i == 0: continue
-            raw_line = lines[i]
-            if raw_line.strip() == ".":
-                # The line is just line break
-                if not desc.endswith("\n"):
-                    desc += "\n"
-                continue
-            elif raw_line.startswith("  "):
-                # The line should be displayed verbatim without word wrapping
-                if not desc.endswith("\n"):
-                    line = "\n%s\n" % raw_line[2:]
-                else:
-                    line = "%s\n" % raw_line[2:]
-            elif raw_line.startswith(" "):
-                # The line is part of a paragraph.
-                if desc.endswith("\n") or desc == "":
-                    # Skip the leading white space
-                    line = raw_line[1:]
-                else:
-                    line = raw_line
-            else:
-                line = raw_line
-                pklog.debug("invalid line %s in description for %s:\n%s" % \
-                            (i, pkg.name, pkg.rawDescription))
-            # Use dots for lists
-            line = re.sub(r"^(\s*)(\*|0|o|-) ", ur"\1\u2022 ", line, 1)
-            # Add current line to the description
-            desc += line
-        return desc
-
-
-def sigquit(signum, frame):
-    pklog.error("Was killed")
-    sys.exit(1)
-
-def debug_exception(type, value, tb):
-    """
-    Provides an interactive debugging session on unhandled exceptions
-    See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65287
-    """
-    if hasattr(sys, 'ps1') or not sys.stderr.isatty() or \
-       not sys.stdin.isatty() or not sys.stdout.isatty() or type==SyntaxError:
-        # Calls the default handler in interactive mode, if output is·
-        # redirected or on syntax errors
-        sys.__excepthook__(type, value, tb)
-    else:
-        import traceback, pdb
-        traceback.print_exception(type, value, tb)
-        print
-        pdb.pm()
-
-def takeover():
-    """
-    Exit the currently running backend
-    """
-    PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
-    PACKAGEKIT_DBUS_INTERFACE = 'org.freedesktop.PackageKitBackend'
-    PACKAGEKIT_DBUS_PATH = '/org/freedesktop/PackageKitBackend'
-    try:
-        bus = dbus.SystemBus()
-    except dbus.DBusException, e:
-        pklog.critical("Unable to connect to dbus: %s" % e)
-        sys.exit(1)
-    proxy = bus.get_object(PACKAGEKIT_DBUS_SERVICE, PACKAGEKIT_DBUS_PATH)
-    iface = dbus.Interface(proxy, PACKAGEKIT_DBUS_INTERFACE)
-    try:
-        iface.Exit()
-    except dbus.DBusException:
-        pass
-
-def run():
-    """
-    Start the apt backend
-    """
-    loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-    bus = dbus.SystemBus(mainloop=loop)
-    bus_name = dbus.service.BusName(PACKAGEKIT_DBUS_SERVICE, bus=bus)
-    manager = PackageKitAptBackend(bus_name, PACKAGEKIT_DBUS_PATH)
-    manager.run()
-
-def main():
-    parser = optparse.OptionParser(description="APT backend for PackageKit")
-    parser.add_option("-t", "--takeover",
-                      action="store_true", dest="takeover",
-                      help="Exit the currently running backend "
-                           "(Only needed by developers)")
-    parser.add_option("-r", "--root",
-                      action="store", type="string", dest="root",
-                      help="Use the given directory as the system root "
-                           "(Only needed by developers)")
-    parser.add_option("-p", "--profile",
-                      action="store", type="string", dest="profile",
-                      help="Store profiling stats in the given file "
-                           "(Only needed by developers)")
-    parser.add_option("-d", "--debug",
-                      action="store_true", dest="debug",
-                      help="Show a lot of additional information and drop to "
-                           "a debugging console on unhandled exceptions "
-                           "(Only needed by developers)")
-    (options, args) = parser.parse_args()
-    if options.debug:
-        pklog.setLevel(logging.DEBUG)
-        sys.excepthook = debug_exception
-
-    if options.root:
-        config = apt_pkg.Config
-        config.Set("Dir", options.root)
-        config.Set("Dir::State::status",
-                   os.path.join(options.root, "/var/lib/dpkg/status"))
-
-    if options.takeover:
-        takeover()
-
-    if options.profile:
-        import hotshot
-        prof = hotshot.Profile(options.profile)
-        prof.runcall(run)
-        prof.close()
-    else:
-        run()
-
-if __name__ == '__main__':
-    main()
-
-# vim: ts=4 et sts=4
diff --git a/backends/apt/aptbackend.py b/backends/apt/aptbackend.py
new file mode 100755
index 0000000..700c325
--- /dev/null
+++ b/backends/apt/aptbackend.py
@@ -0,0 +1,2236 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+Provides an apt backend to PackageKit
+
+Copyright (C) 2007 Ali Sabil <ali.sabil at gmail.com>
+Copyright (C) 2007 Tom Parker <palfrey at tevp.net>
+Copyright (C) 2008 Sebastian Heinlein <glatzor at ubuntu.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.
+"""
+
+__author__  = "Sebastian Heinlein <devel at glatzor.de>"
+
+import errno
+import fcntl
+import gdbm
+import httplib
+import locale
+import logging
+import optparse
+import os
+import pty
+import re
+import signal
+import shutil
+import socket
+import stat
+import string
+import subprocess
+import sys
+import time
+import threading
+import urllib2
+import warnings
+
+import apt
+import apt.debfile
+import apt_pkg
+import dbus
+import dbus.glib
+import dbus.service
+import dbus.mainloop.glib
+import gobject
+
+from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress, pklog, threaded, serialize
+from packagekit.enums import *
+
+
+warnings.filterwarnings(action='ignore', category=FutureWarning)
+
+PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
+
+apt_pkg.InitConfig()
+apt_pkg.Config.Set("DPkg::Options::", '--force-confdef')
+apt_pkg.Config.Set("DPkg::Options::", '--force-confold')
+
+# Xapian database is optionally used to speed up package description search
+XAPIAN_DB_PATH = os.environ.get("AXI_DB_PATH", "/var/lib/apt-xapian-index")
+XAPIAN_DB = XAPIAN_DB_PATH + "/index"
+XAPIAN_DB_VALUES = XAPIAN_DB_PATH + "/values"
+XAPIAN_SUPPORT = False
+try:
+    import xapian
+except ImportError:
+    pass
+else:
+    if os.access(XAPIAN_DB, os.R_OK):
+        pklog.debug("Use XAPIAN for the search")
+        XAPIAN_SUPPORT = True
+
+# SoftwareProperties is required to proivde information about repositories
+try:
+    import softwareproperties.SoftwareProperties
+except ImportError:
+    REPOS_SUPPORT = False
+else:
+    REPOS_SUPPORT = True
+
+# Check if update-manager-core is installed to get aware of the
+# latest distro releases
+try:
+    from UpdateManager.Core.MetaRelease import MetaReleaseCore
+except ImportError:
+    META_RELEASE_SUPPORT = False
+else:
+    META_RELEASE_SUPPORT = True
+
+
+# Set a timeout for the changelog download
+socket.setdefaulttimeout(2)
+
+# Required for daemon mode
+os.putenv("PATH",
+          "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+# Avoid questions from the maintainer scripts as far as possible
+os.putenv("DEBIAN_FRONTEND", "noninteractive")
+os.putenv("APT_LISTCHANGES_FRONTEND", "none")
+
+# Setup threading support
+gobject.threads_init()
+dbus.glib.threads_init()
+
+# Map Debian sections to the PackageKit group name space
+SECTION_GROUP_MAP = {
+    "admin" : GROUP_ADMIN_TOOLS,
+    "base" : GROUP_SYSTEM,
+    "comm" : GROUP_COMMUNICATION,
+    "devel" : GROUP_PROGRAMMING,
+    "doc" : GROUP_DOCUMENTATION,
+    "editors" : GROUP_PUBLISHING,
+    "electronics" : GROUP_ELECTRONICS,
+    "embedded" : GROUP_SYSTEM,
+    "games" : GROUP_GAMES,
+    "gnome" : GROUP_DESKTOP_GNOME,
+    "graphics" : GROUP_GRAPHICS,
+    "hamradio" : GROUP_COMMUNICATION,
+    "interpreters" : GROUP_PROGRAMMING,
+    "kde" : GROUP_DESKTOP_KDE,
+    "libdevel" : GROUP_PROGRAMMING,
+    "libs" : GROUP_SYSTEM,
+    "mail" : GROUP_INTERNET,
+    "math" : GROUP_SCIENCE,
+    "misc" : GROUP_OTHER,
+    "net" : GROUP_NETWORK,
+    "news" : GROUP_INTERNET,
+    "oldlibs" : GROUP_LEGACY,
+    "otherosfs" : GROUP_SYSTEM,
+    "perl" : GROUP_PROGRAMMING,
+    "python" : GROUP_PROGRAMMING,
+    "science" : GROUP_SCIENCE,
+    "shells" : GROUP_SYSTEM,
+    "sound" : GROUP_MULTIMEDIA,
+    "tex" : GROUP_PUBLISHING,
+    "text" : GROUP_PUBLISHING,
+    "utils" : GROUP_ACCESSORIES,
+    "web" : GROUP_INTERNET,
+    "x11" : GROUP_DESKTOP_OTHER,
+    "unknown" : GROUP_UNKNOWN,
+    "alien" : GROUP_UNKNOWN,
+    "translations" : GROUP_LOCALIZATION,
+    "metapackages" : GROUP_COLLECTIONS }
+
+# Regular expressions to detect bug numbers in changelogs according to the
+# Debian Policy Chapter 4.4. For details see the footnote 16:
+# http://www.debian.org/doc/debian-policy/footnotes.html#f16
+MATCH_BUG_CLOSES_DEBIAN=r"closes:\s*(?:bug)?\#?\s?\d+(?:,\s*(?:bug)?\#?\s?\d+)*"
+MATCH_BUG_NUMBERS=r"\#?\s?(\d+)"
+# URL pointing to a bug in the Debian bug tracker
+HREF_BUG_DEBIAN="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s"
+
+# Regular expression to find cve references
+MATCH_CVE="CVE-\d{4}-\d{4}"
+HREF_CVE="http://web.nvd.nist.gov/view/vuln/detail?vulnId=%s"
+
+def unlock_cache_afterwards(func):
+    '''
+    Make sure that the package cache is unlocked after the decorated function
+    was called
+    '''
+    def wrapper(*args, **kwargs):
+        backend = args[0]
+        func(*args, **kwargs)
+        backend._unlock_cache()
+    wrapper.__name__ = func.__name__
+    return wrapper
+
+
+class PKError(Exception):
+    pass
+
+class PackageManagerFailedPKError(PKError):
+    def __init__(self, msg, pkg, output):
+        self.message = msg
+        self.package = pkg
+        self.output = output
+
+class InstallTimeOutPKError(PKError):
+    pass
+
+class PackageKitCache(apt.cache.Cache):
+    """
+    Enhanced version of the apt.cache.Cache class which supports some features
+    which can only be found in the consolidate branch of python-apt
+    """
+    def __iter__(self):
+        """
+        Let the cache behave like a sorted list of packages
+        """
+        for pkgname in sorted(self._dict.keys()):
+            yield self._dict[pkgname]
+        raise StopIteration
+
+    def isVirtualPackage(self, name):
+        """ 
+        Return True if the package of the given name is a virtual package
+        """
+        try:
+            virtual_pkg = self._cache[name]
+        except KeyError:
+            return False
+        if len(virtual_pkg.VersionList) == 0:
+            return True
+        return False
+
+    def getProvidingPackages(self, virtual):
+        """
+        Return a list of packages which provide the virtual package of the
+        specified name
+        """
+        providers = []
+        try:
+            vp = self._cache[virtual]
+            if len(vp.VersionList) != 0:
+                return providers
+        except KeyError:
+            return providers
+        for pkg in self:
+            v = self._depcache.GetCandidateVer(pkg._pkg)
+            if v == None:
+                continue
+            for p in v.ProvidesList:
+                #print virtual
+                #print p[0]
+                if virtual == p[0]:
+                    # we found a pkg that provides this virtual
+                    # pkg, check if the proivdes is any good
+                    providers.append(pkg)
+                    #cand = self._cache[pkg.name]
+                    #candver = self._cache._depcache.GetCandidateVer(cand._pkg)
+                    #instver = cand._pkg.CurrentVer
+                    #res = apt_pkg.CheckDep(candver.VerStr,oper,ver)
+                    #if res == True:
+                    #    self._dbg(1,"we can use %s" % pkg.name)
+                    #    or_found = True
+                    #    break
+        return providers
+
+    def clear(self):
+        """ Unmark all changes """
+        self._depcache.Init()
+
+
+class DpkgInstallProgress(apt.progress.InstallProgress):
+    """
+    Class to initiate and monitor installation of local package files with dpkg
+    """
+    #FIXME: Use the merged DpkgInstallProgress of python-apt
+    def recover(self):
+        """
+        Run "dpkg --configure -a"
+        """
+        cmd = ["/usr/bin/dpkg", "--status-fd", str(self.writefd),
+               "--root", apt_pkg.Config["Dir"],
+               "--force-confdef", "--force-confold", 
+               "--configure", "-a"]
+        self.run(cmd)
+
+    def install(self, filenames):
+        """
+        Install the given package using a dpkg command line call
+        """
+        cmd = ["/usr/bin/dpkg", "--force-confdef", "--force-confold",
+               "--status-fd", str(self.writefd), 
+               "--root", apt_pkg.Config["Dir"], "-i"]
+        cmd.extend(map(lambda f: str(f), filenames))
+        self.run(cmd)
+
+    def run(self, cmd):
+        """
+        Run and monitor a dpkg command line call
+        """
+        pklog.debug("Executing: %s" % cmd)
+        (self.master_fd, slave) = pty.openpty()
+        fcntl.fcntl(self.master_fd, fcntl.F_SETFL, os.O_NONBLOCK)
+        p = subprocess.Popen(cmd, stdout=slave, stdin=slave)
+        self.child_pid = p.pid
+        res = self.waitChild()
+        return res
+
+    def updateInterface(self):
+        """
+        Process status messages from dpkg
+        """
+        if self.statusfd == None:
+            return
+        try:
+            while not self.read.endswith("\n"):
+                self.read += os.read(self.statusfd.fileno(), 1)
+        except OSError, (error_no, error_str):
+            # resource temporarly unavailable is ignored
+            if error_no not in [errno.EAGAIN, errno.EWOULDBLOCK]:
+                print error_str
+        if self.read.endswith("\n"):
+            statusl = string.split(self.read, ":")
+            if len(statusl) < 3:
+                pklog.warn("got garbage from dpkg: '%s'" % self.read)
+                self.read = ""
+            status = statusl[2].strip()
+            pkg = statusl[1].strip()
+            #print status
+            if status == "error":
+                self.error(pkg, status)
+            elif status == "conffile-prompt":
+                # we get a string like this:
+                # 'current-conffile' 'new-conffile' useredited distedited
+                match = re.search(".+conffile-prompt : '(.+)' '(.+)'",
+                                  self.read)
+                self.conffile(match.group(1), match.group(2))
+            else:
+                pklog.debug("Dpkg status: %s" % status)
+                self.status = status
+            self.read = ""
+
+
+class PackageKitOpProgress(apt.progress.OpProgress):
+    '''
+    Handle the cache opening process
+    '''
+    def __init__(self, backend, prange=(0,100), progress=True):
+        self._backend = backend
+        apt.progress.OpProgress.__init__(self)
+        self.steps = []
+        for v in [0.12, 0.25, 0.50, 0.75, 1.00]:
+            s = prange[0] + (prange[1] - prange[0]) * v
+            self.steps.append(s)
+        self.pstart = float(prange[0])
+        self.pend = self.steps.pop(0)
+        self.pprev = None
+        self.show_progress = progress
+
+    # OpProgress callbacks
+    def update(self, percent):
+        progress = int(self.pstart + percent / 100 * (self.pend - self.pstart))
+        if self.show_progress == True and self.pprev < progress:
+            self._backend.PercentageChanged(progress)
+            self.pprev = progress
+
+    def done(self):
+        self.pstart = self.pend
+        try:
+            self.pend = self.steps.pop(0)
+        except:
+            pklog.warning("An additional step to open the cache is required")
+
+
+class PackageKitFetchProgress(apt.progress.FetchProgress):
+    '''
+    Handle the package download process
+    '''
+    def __init__(self, backend, prange=(0,100)):
+        self._backend = backend
+        apt.progress.FetchProgress.__init__(self)
+        self.pstart = prange[0]
+        self.pend = prange[1]
+        self.pprev = None
+
+    def pulse(self):
+        apt.progress.FetchProgress.pulse(self)
+        # Strange, but we seem to need this to detect a cancel immediately
+        time.sleep(0.01)
+        if self._backend._canceled.isSet():
+            return False
+        progress = int(self.pstart + self.percent/100 * \
+                       (self.pend - self.pstart))
+        if self.pprev < progress:
+            self._backend.PercentageChanged(progress)
+            self.pprev = progress
+        return True
+
+    def start(self):
+        self._backend.StatusChanged(STATUS_DOWNLOAD)
+        self._backend.AllowCancel(True)
+
+    def stop(self):
+        self._backend.PercentageChanged(self.pend)
+        self._backend.AllowCancel(False)
+
+    def mediaChange(self, medium, drive):
+        #FIXME: Raise an expcetion and handle it in _commit_changes
+        #       Strangly _commit_changes does not catch the expcetion
+        self._backend.Message(MESSAGE_UNKNOWN,
+                              "Installing from CD-Rom (%s) is not "
+                              "supported." % medium)
+        return False
+
+
+class PackageKitInstallProgress(apt.progress.InstallProgress):
+    '''
+    Handle the installation and removal process. Bits taken from
+    DistUpgradeViewNonInteractive.
+    '''
+    def __init__(self, backend, prange=(0,100)):
+        apt.progress.InstallProgress.__init__(self)
+        self._backend = backend
+        self.pstart = prange[0]
+        self.pend = prange[1]
+        self.pprev = None
+        self.last_activity = None
+        self.conffile_prompts = set()
+        # insanly long timeout to be able to kill hanging maintainer scripts
+        self.timeout = 10 * 60
+        self.start_time = None
+        self.output = ""
+        self.master_fd = None
+        self.child_pid = None
+
+    def statusChange(self, pkg, percent, status):
+        self.last_activity = time.time()
+        progress = self.pstart + percent/100 * (self.pend - self.pstart)
+        if self.pprev < progress:
+            self._backend.PercentageChanged(int(progress))
+            self.pprev = progress
+        pklog.debug("APT status: %s" % status)
+
+    def startUpdate(self):
+        # The apt system lock was set by _lock_cache() before
+        self._backend._unlock_cache()
+        self._backend.StatusChanged(STATUS_COMMIT)
+        self.last_activity = time.time()
+        self.start_time = time.time()
+
+    def fork(self):
+        pklog.debug("fork()")
+        (pid, self.master_fd) = pty.fork()
+        if pid != 0:
+            fcntl.fcntl(self.master_fd, fcntl.F_SETFL, os.O_NONBLOCK)
+        return pid
+
+    def updateInterface(self):
+        apt.progress.InstallProgress.updateInterface(self)
+        # Collect the output from the package manager
+        try:
+            out = os.read(self.master_fd, 512)
+            self.output = self.output + out
+            pklog.debug("APT out: %s " % out)
+        except OSError:
+            pass
+        # catch a time out by sending crtl+c
+        if self.last_activity + self.timeout < time.time():
+            pklog.critical("no activity for %s time sending ctrl-c" \
+                           % self.timeout)
+            os.write(self.master_fd, chr(3))
+            #FIXME: include this into the normal install progress and add 
+            #       correct package information
+            raise InstallTimeOutPKError(self.output)
+
+    def conffile(self, current, new):
+        pklog.warning("Config file prompt: '%s' (sending no)" % current)
+        self.conffile_prompts.add(new)
+
+    def error(self, pkg, msg):
+        raise PackageManagerFailedPKError(pkg, msg, self.output)
+
+    def finishUpdate(self):
+        pklog.debug("finishUpdate()")
+        if self.conffile_prompts:
+            self._backend.Message(MESSAGE_CONFIG_FILES_CHANGED, 
+                                  "The following conffile prompts were found "
+                                  "and need investiagtion: %s" % \
+                                  "\n".join(self.conffile_prompts))
+        # Check for required restarts
+        if os.path.exists("/var/run/reboot-required") and \
+           os.path.getmtime("/var/run/reboot-required") > self.start_time:
+            self._backend.RequireRestart(RESTART_SYSTEM, "")
+
+
+class PackageKitDpkgInstallProgress(DpkgInstallProgress,
+                                    PackageKitInstallProgress):
+    """
+    Class to integrate the progress of core dpkg operations into PackageKit
+    """
+    def run(self, filenames):
+        return DpkgInstallProgress.run(self, filenames)
+
+    def updateInterface(self):
+        DpkgInstallProgress.updateInterface(self)
+        try:
+            out = os.read(self.master_fd, 512)
+            self.output += out
+            if out != "": pklog.debug("Dpkg out: %s" % out)
+        except OSError:
+            pass
+        # we timed out, send ctrl-c
+        if self.last_activity + self.timeout < time.time():
+            pklog.critical("no activity for %s time sending "
+                           "ctrl-c" % self.timeout)
+            os.write(self.master_fd, chr(3))
+            raise InstallTimeOutPKError(self.output)
+
+
+if REPOS_SUPPORT == True:
+    class PackageKitSoftwareProperties(softwareproperties.SoftwareProperties.SoftwareProperties):
+        """
+        Helper class to fix a siily bug in python-software-properties
+        """
+        def set_modified_sourceslist(self):
+            self.save_sourceslist()
+
+
+class PackageKitAptBackend(PackageKitBaseBackend):
+    '''
+    PackageKit backend for apt
+    '''
+    def __init__(self, bus_name, dbus_path):
+        pklog.info("Initializing APT backend")
+        signal.signal(signal.SIGQUIT, sigquit)
+        self._cache = None
+        self._canceled = threading.Event()
+        self._canceled.clear()
+        self._lock = threading.Lock()
+        self._last_cache_refresh = None
+        PackageKitBaseBackend.__init__(self, bus_name, dbus_path)
+
+    # Methods ( client -> engine -> backend )
+
+    def doInit(self):
+        pklog.info("Initializing cache")
+        self.StatusChanged(STATUS_RUNNING)
+        self.AllowCancel(False)
+        self.NoPercentageUpdates()
+        self._open_cache(progress=False)
+
+    @serialize
+    def doExit(self):
+        gobject.idle_add(self._doExitDelay)
+
+    def doCancel(self):
+        pklog.info("Canceling current action")
+        self.StatusChanged(STATUS_CANCEL)
+        self._canceled.set()
+        self._canceled.wait()
+
+    @serialize
+    @threaded
+    def doSearchFile(self, filters, filename):
+        '''
+        Implement the apt2-search-file functionality
+
+        Apt specific: Works only for installed files. Since config files are
+        not removed by default even not installed packages can be reported.
+        '''
+        pklog.info("Searching for file: %s" % filename)
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(True)
+
+        for pkg in self._cache:
+            if self._check_canceled(): return False
+            for installed_file in self._get_installed_files(pkg):
+                if filename in installed_file:
+                    self._emit_visible_package(filters, pkg)
+                    break
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doSearchGroup(self, filters, group):
+        '''
+        Implement the apt2-search-group functionality
+        '''
+        pklog.info("Searching for group: %s" % group)
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(True)
+
+        for pkg in self._cache:
+            if self._check_canceled(): return False
+            elif self._get_package_group(pkg) == group:
+                self._emit_visible_package(filters, pkg)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doSearchName(self, filters, search):
+        '''
+        Implement the apt2-search-name functionality
+        '''
+        pklog.info("Searching for package name: %s" % search)
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(True)
+
+        for pkg in self._cache:
+            if self._check_canceled(): return False
+            elif search in pkg.name:
+                self._emit_visible_package(filters, pkg)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doSearchDetails(self, filters, search):
+        '''
+        Implement the apt2-search-details functionality
+        '''
+        pklog.info("Searching for package name: %s" % search)
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(True)
+        results = []
+
+        if XAPIAN_SUPPORT == True:
+            search_flags = (xapian.QueryParser.FLAG_BOOLEAN |
+                            xapian.QueryParser.FLAG_PHRASE |
+                            xapian.QueryParser.FLAG_LOVEHATE |
+                            xapian.QueryParser.FLAG_BOOLEAN_ANY_CASE)
+            pklog.debug("Performing xapian db based search")
+            db = xapian.Database(XAPIAN_DB)
+            parser = xapian.QueryParser()
+            query = parser.parse_query(unicode(search),
+                                       search_flags)
+            enquire = xapian.Enquire(db)
+            enquire.set_query(query)
+            matches = enquire.get_mset(0, 1000)
+            for r in  map(lambda m: m[xapian.MSET_DOCUMENT].get_data(),
+                          enquire.get_mset(0,1000)):
+                if self._cache.has_key(r):
+                    results.append(self._cache[r])
+        else:
+            pklog.debug("Performing apt cache based search")
+            for p in self._cache._dict.values():
+                if self._check_canceled(): return
+                needle = search.strip().lower()
+                haystack = p.description.lower()
+                if p.name.find(needle) >= 0 or haystack.find(needle) >= 0:
+                    results.append(p)
+
+        for r in results:
+            if self._check_canceled(): return
+            self._emit_visible_package(filters, r)
+
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetDistroUpgrades(self):
+        '''
+        Implement the {backend}-get-distro-upgrades functionality
+        '''
+        pklog.info("Get distro upgrades")
+        self.StatusChanged(STATUS_INFO)
+        self.AllowCancel(False)
+        self.NoPercentageUpdates()
+
+        if META_RELEASE_SUPPORT == False:
+            if self._cache.has_key("update-manager-core") and \
+               self._cache["update-manager-core"].isInstalled == False:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "Please install the package update-manager-core to get notified "
+                               "of the latest distribution releases.")
+            else:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "Please make sure that update-manager-core is"
+                               "correctly installed.")
+            self.Finished(EXIT_FAILED)
+            return
+
+        #FIXME Evil to start the download during init
+        meta_release = MetaReleaseCore(False, False)
+        #FIXME: should use a lock
+        while meta_release.downloading:
+            time.sleep(1)
+        #FIXME: Add support for description
+        if meta_release.new_dist != None:
+            self.DistroUpgrade("stable", 
+                               "%s %s" % (meta_release.new_dist.name,
+                                          meta_release.new_dist.version),
+                               "The latest stable release")
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetUpdates(self, filters):
+        '''
+        Implement the {backend}-get-update functionality
+        '''
+        def succeeds_security_update(pkg):
+            """
+            Return True if an update succeeds a previous security update
+
+            An example would be a package with version 1.1 in the security
+            archive and 1.1.1 in the archive of proposed updates or the
+            same version in both archives.
+            """
+            inst_ver = pkg._pkg.CurrentVer
+            for ver in pkg._pkg.VersionList:
+                # Skip versions which are not later
+                if inst_ver and \
+                   apt_pkg.VersionCompare(ver.VerStr, inst_ver.VerStr) <= 0:
+                    continue
+                for(verFileIter, index) in ver.FileList:
+                    if verFileIter.Origin in ["Debian", "Ubuntu"] and \
+                       (verFileIter.Archive.endswith("-security") or \
+                        verFileIter.Label == "Debian-Security"):
+                        indexfile = pkg._list.FindIndex(verFileIter)
+                        if indexfile and indexfile.IsTrusted:
+                            return True
+            return False
+        #FIXME: Implment the basename filter
+        pklog.info("Get updates")
+        self.StatusChanged(STATUS_QUERY)
+        self.AllowCancel(True)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self._cache.upgrade(False)
+        updates = filter(lambda p: self._cache[p].isUpgradable,
+                         self._cache.keys())
+        for pkg in self._cache.getChanges():
+            if self._check_canceled(): return False
+            else:
+                updates.remove(pkg.name)
+                info = INFO_NORMAL
+                archive = pkg.candidateOrigin[0].archive
+                origin = pkg.candidateOrigin[0].origin
+                trusted = pkg.candidateOrigin[0].trusted
+                label = pkg.candidateOrigin[0].label
+                if origin in ["Debian", "Ubuntu"] and trusted == True:
+                    if archive.endswith("-security") or \
+                       label == "Debian-Security":
+                        info = INFO_SECURITY
+                    elif succeeds_security_update(pkg):
+                        pklog.debug("Update of %s succeeds a security "
+                                    "update. Raising its priority." % pkg.name)
+                        info = INFO_SECURITY
+                    elif archive.endswith("-backports"):
+                        info = INFO_ENHANCEMENT
+                    elif archive.endswith("-updates"):
+                        info = INFO_BUGFIX
+                if origin in ["Backports.org archive"] and trusted == True:
+                    info = INFO_ENHANCEMENT
+                self._emit_package(pkg, info, force_candidate=True)
+        # Report packages that are upgradable but cannot be upgraded
+        for missed in updates:
+            self._emit_package(self._cache[missed], INFO_BLOCKED)
+        self._cache.clear()
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetUpdateDetail(self, pkg_ids):
+        '''
+        Implement the {backend}-get-update-details functionality
+        '''
+        def get_bug_urls(changelog):
+            """
+            Create a list of urls pointing to closed bugs in the changelog
+            """
+            urls = []
+            #FIXME: Add support for Launchpad/Ubuntu
+            for r in re.findall(MATCH_BUG_CLOSES_DEBIAN, changelog,
+                                re.IGNORECASE | re.MULTILINE):
+                urls.extend(map(lambda b: HREF_BUG_DEBIAN % b,
+                                re.findall(MATCH_BUG_NUMBERS, r)))
+            return urls
+
+        def get_cve_urls(changelog):
+            """
+            Create a list of urls pointing to cves referred in the changelog
+            """
+            return map(lambda c: HREF_CVE % c,
+                       re.findall(MATCH_CVE, changelog, re.MULTILINE))
+
+        pklog.info("Get update details of %s" % pkg_ids)
+        self.StatusChanged(STATUS_INFO)
+        self.NoPercentageUpdates()
+        self.AllowCancel(True)
+        self._check_init(progress=False)
+        for pkg_id in pkg_ids:
+            if self._check_canceled(): return
+            pkg = self._find_package_by_id(pkg_id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s isn't available" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            # FIXME add some real data
+            updates = self.get_id_from_package(pkg, force_candidate=False)
+            obsoletes = ""
+            vendor_url = ""
+            restart = ""
+            update_text = ""
+            state = ""
+            issued = ""
+            updated = ""
+            #FIXME: Replace this method with the python-apt one as soon as the
+            #       consolidate branch gets merged
+            self.StatusChanged(STATUS_DOWNLOAD_CHANGELOG)
+            changelog = self._get_changelog(pkg)
+            self.StatusChanged(STATUS_INFO)
+            bugzilla_url = ";".join(get_bug_urls(changelog))
+            cve_url = ";".join(get_cve_urls(changelog))
+            self.UpdateDetail(pkg_id, updates, obsoletes, vendor_url,
+                              bugzilla_url, cve_url, restart, update_text,
+                              changelog, state, issued, updated)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetDetails(self, pkg_ids):
+        '''
+        Implement the {backend}-get-details functionality
+        '''
+        pklog.info("Get details of %s" % pkg_ids)
+        self.StatusChanged(STATUS_DEP_RESOLVE)
+        self.NoPercentageUpdates()
+        self.AllowCancel(True)
+        self._check_init(progress=False)
+        for pkg_id in pkg_ids:
+            if self._check_canceled(): return
+            pkg = self._find_package_by_id(pkg_id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s isn't available" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            desc = self._get_package_description(pkg)
+            #FIXME: We need more fine grained license information!
+            candidate = pkg.candidateOrigin
+            if candidate != None and  \
+               candidate[0].component in ["main", "universe"] and \
+               candidate[0].origin in ["Debian", "Ubuntu"]:
+                license = "free"
+            else:
+                license = "unknown"
+            group = self._get_package_group(pkg)
+            self.Details(pkg_id, license, group, desc,
+                         pkg.homepage, pkg.packageSize)
+            self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    @unlock_cache_afterwards
+    def doUpdateSystem(self):
+        '''
+        Implement the {backend}-update-system functionality
+        '''
+        pklog.info("Upgrading system")
+        if not self._lock_cache(): return
+        self.StatusChanged(STATUS_UPDATE)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        self._check_init(prange=(0,5))
+        try:
+            self._cache.upgrade(distUpgrade=False)
+        except:
+            self._cache.clear()
+            self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+                           "Failed to upgrade the system.")
+            self.Finished(EXIT_FAILED)
+            return
+        if not self._commit_changes(): return False
+        self.PercentageChanged(100)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    @unlock_cache_afterwards
+    def doRemovePackages(self, ids, deps=True, auto=False):
+        '''
+        Implement the {backend}-remove functionality
+        '''
+        pklog.info("Removing package(s): id %s" % ids)
+        if not self._lock_cache(): return
+        self.StatusChanged(STATUS_REMOVE)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        self._check_init(prange=(0,10))
+        pkgs=[]
+        for id in ids:
+            pkg = self._find_package_by_id(id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s isn't available" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            if not pkg.isInstalled:
+                self.ErrorCode(ERROR_PACKAGE_NOT_INSTALLED,
+                               "Package %s isn't installed" % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+            pkgs.append(pkg.name[:])
+            if pkg._pkg.Essential == True:
+                self.ErrorCode(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE,
+                               "Package %s cannot be removed." % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+            try:
+                pkg.markDelete()
+            except:
+                self._open_cache(prange=(90,99))
+                self.ErrorCode(ERROR_UNKNOWN, "Removal of %s failed" % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+        if not self._commit_changes(fetch_range=(10,10),
+                                    install_range=(10,90)):
+            return False
+        self._open_cache(prange=(90,99))
+        for p in pkgs:
+            if self._cache.has_key(p) and self._cache[p].isInstalled:
+                self.ErrorCode(ERROR_UNKNOWN, "%s is still installed" % p)
+                self.Finished(EXIT_FAILED)
+                return
+        self.PercentageChanged(100)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetRepoList(self, filters):
+        '''
+        Implement the {backend}-get-repo-list functionality
+
+        FIXME: should we use the abstration of software-properties or provide
+               low level access using pure aptsources?
+        '''
+        pklog.info("Getting repository list: %s" % filters)
+        self.StatusChanged(STATUS_INFO)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        if REPOS_SUPPORT == False:
+            if self._cache.has_key("python-software-properties") and \
+               self._cache["python-software-properties"].isInstalled == False:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "Please install the package "
+                               "python-software-properties to handle repositories")
+            else:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "Please make sure that python-software-properties is"
+                               "correctly installed.")
+            self.Finished(EXIT_FAILED)
+            return
+        filter_list = filters.split(";")
+        repos = PackageKitSoftwareProperties()
+        # Emit distro components as virtual repositories
+        for comp in repos.distro.source_template.components:
+            repo_id = "%s_comp_%s" % (repos.distro.id, comp.name)
+            description = "%s %s - %s (%s)" % (repos.distro.id,
+                                               repos.distro.release,
+                                               comp.get_description(),
+                                               comp.name)
+            #FIXME: There is no inconsitent state in PackageKit
+            enabled = repos.get_comp_download_state(comp)[0]
+            if not FILTER_DEVELOPMENT in filter_list:
+                self.RepoDetail(repo_id, description, enabled)
+        # Emit distro's virtual update repositories
+        for template in repos.distro.source_template.children:
+            repo_id = "%s_child_%s" % (repos.distro.id, template.name)
+            description = "%s %s - %s (%s)" % (repos.distro.id,
+                                               repos.distro.release,
+                                               template.description,
+                                               template.name)
+            #FIXME: There is no inconsitent state in PackageKit
+            enabled = repos.get_comp_child_state(template)[0]
+            if not FILTER_DEVELOPMENT in filter_list:
+                self.RepoDetail(repo_id, description, enabled)
+        # Emit distro's cdrom sources
+        for source in repos.get_cdrom_sources():
+            if FILTER_NOT_DEVELOPMENT in filter_list and \
+               source.type in ("deb-src", "rpm-src"):
+                continue
+            enabled = not source.disabled
+            # Remove markups from the description
+            description = re.sub(r"</?b>", "", repos.render_source(source))
+            repo_id = "cdrom_%s_%s" % (source.uri, source.dist)
+            repo_id.join(map(lambda c: "_%s" % c, source.comps))
+            self.RepoDetail(repo_id, description, enabled)
+        # Emit distro's virtual source code repositoriy
+        if not FILTER_NOT_DEVELOPMENT in filter_list:
+            repo_id = "%s_source" % repos.distro.id
+            enabled = repos.get_source_code_state() or False
+            #FIXME: no translation :(
+            description = "%s %s - Source code" % (repos.distro.id, 
+                                                   repos.distro.release)
+            self.RepoDetail(repo_id, description, enabled)
+        # Emit third party repositories
+        for source in repos.get_isv_sources():
+            if FILTER_NOT_DEVELOPMENT in filter_list and \
+               source.type in ("deb-src", "rpm-src"):
+                continue
+            enabled = not source.disabled
+            # Remove markups from the description
+            description = re.sub(r"</?b>", "", repos.render_source(source))
+            repo_id = "isv_%s_%s" % (source.uri, source.dist)
+            repo_id.join(map(lambda c: "_%s" % c, source.comps))
+            self.RepoDetail(repo_id, description, enabled)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doRepoEnable(self, repo_id, enable):
+        '''
+        Implement the {backend}-repo-enable functionality
+
+        FIXME: should we use the abstration of software-properties or provide
+               low level access using pure aptsources?
+        '''
+        pklog.info("Enabling repository: %s %s" % (repo_id, enable))
+        self.StatusChanged(STATUS_RUNNING)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        if REPOS_SUPPORT == False:
+            if self._cache.has_key("python-software-properties") and \
+               self._cache["python-software-properties"].isInstalled == False:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "Please install the package "
+                               "python-software-properties to handle repositories")
+            else:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "Please make sure that python-software-properties is"
+                               "correctly installed.")
+            self.Finished(EXIT_FAILED)
+            return
+        repos = PackageKitSoftwareProperties()
+
+        found = False
+        # Check if the repo_id matches a distro component, e.g. main
+        if repo_id.startswith("%s_comp_" % repos.distro.id):
+            for comp in repos.distro.source_template.components:
+                if repo_id == "%s_comp_%s" % (repos.distro.id, comp.name):
+                    if enable == repos.get_comp_download_state(comp)[0]:
+                        pklog.debug("Repository is already enabled")
+                        pass
+                    if enable == True:
+                        repos.enable_component(comp.name)
+                    else:
+                        repos.disable_component(comp.name)
+                    found = True
+                    break
+        # Check if the repo_id matches a distro child repository, e.g. hardy-updates
+        elif repo_id.startswith("%s_child_" % repos.distro.id):
+            for template in repos.distro.source_template.children:
+                if repo_id == "%s_child_%s" % (repos.distro.id, template.name):
+                    if enable == repos.get_comp_child_state(template)[0]:
+                        pklog.debug("Repository is already enabled")
+                        pass
+                    elif enable == True:
+                        repos.enable_child_source(template)
+                    else:
+                        repos.disable_child_source(template)
+                    found = True
+                    break
+        # Check if the repo_id matches a cdrom repository
+        elif repo_id.startswith("cdrom_"):
+            for source in repos.get_isv_sources():
+                source_id = "cdrom_%s_%s" % (source.uri, source.dist)
+                source_id.join(map(lambda c: "_%s" % c, source.comps))
+                if repo_id == source_id:
+                    if source.disabled == enable:
+                        source.disabled = not enable
+                        repos.save_sourceslist()
+                    else:
+                        pklog.debug("Repository is already enabled")
+                    found = True
+                    break
+        # Check if the repo_id matches an isv repository
+        elif repo_id.startswith("isv_"):
+            for source in repos.get_isv_sources():
+                source_id = "isv_%s_%s" % (source.uri, source.dist)
+                source_id.join(map(lambda c: "_%s" % c, source.comps))
+                if repo_id == source_id:
+                    if source.disabled == enable:
+                        source.disabled = not enable
+                        repos.save_sourceslist()
+                    else:
+                        pklog.debug("Repository is already enabled")
+                    found = True
+                    break
+        if found == False:
+            self.ErrorCode(ERROR_REPO_NOT_AVAILABLE,
+                           "The repository of the id %s isn't available" % repo_id)
+            self.Finished(EXIT_FAILED)
+            return
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    @unlock_cache_afterwards
+    def doUpdatePackages(self, ids):
+        '''
+        Implement the {backend}-update functionality
+        '''
+        pklog.info("Updating package with id %s" % ids)
+        if not self._lock_cache(): return
+        self.StatusChanged(STATUS_UPDATE)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        self._check_init(prange=(0,10))
+        pkgs=[]
+        for id in ids:
+            pkg = self._find_package_by_id(id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s isn't available" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            if not pkg.isUpgradable:
+                self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,
+                               "Package %s is already up-to-date" % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+            pkgs.append(pkg.name[:])
+            try:
+                pkg.markUpgrade()
+            except:
+                self._open_cache(prange=(90,100))
+                self.ErrorCode(ERROR_UNKNOWN, "%s could not be queued for "
+                                              "update" % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+        if not self._commit_changes(): return False
+        self._open_cache(prange=(90,100))
+        self.PercentageChanged(100)
+        pklog.debug("Checking success of operation")
+        for p in pkgs:
+            if not self._cache.has_key(p) or not self._cache[p].isInstalled \
+               or self._cache[p].isUpgradable:
+                self.ErrorCode(ERROR_UNKNOWN, "%s was not updated" % p)
+                self.Finished(EXIT_FAILED)
+                return
+        pklog.debug("Sending success signal")
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doDownloadPackages(self, ids, dest):
+        '''
+        Implement the {backend}-download-packages functionality
+        '''
+        pklog.info("Downloading packages: %s" % ids)
+        self.StatusChanged(STATUS_DOWNLOAD)
+        self.AllowCancel(True)
+        self.PercentageChanged(0)
+        # Check the destination directory
+        if not os.path.isdir(dest) or not os.access(dest, os.W_OK):
+            self.ErrorCode(ERROR_UNKNOWN,
+                           "The directory '%s' is not writable" % dest)
+            self.Finished(EXIT_FAILED)
+            return
+        # Setup the fetcher
+        self._check_init(prange=(0,10))
+        progress = PackageKitFetchProgress(self, prange=(10,90))
+        fetcher = apt_pkg.GetAcquire(progress)
+        pm = apt_pkg.GetPackageManager(self._cache._depcache)
+        recs = apt_pkg.GetPkgRecords(self._cache._cache)
+        list = apt_pkg.GetPkgSourceList()
+        list.ReadMainList()
+        # Mark installed packages for reinstallation and not installed packages
+        # for installation without dependencies
+        for id in ids:
+            if self._check_canceled(): return
+            pkg = self._find_package_by_id(id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "There is no package %s" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            if pkg.isInstalled:
+                self._cache._depcache.SetReInstall(pkg._pkg, True)
+            else:
+                self._cache._depcache.MarkInstall(pkg._pkg, False)
+        # Download 
+        pm.GetArchives(fetcher, list, recs)
+        res = fetcher.Run()
+        self._cache.clear()
+        self.PercentageChanged(95)
+        # Copy files from cache to final destination
+        for item in fetcher.Items:
+            if self._check_canceled(): return
+            pklog.debug("Download item: %s" % item)
+            if (item.Status != item.StatDone and not item.StatIdle) or \
+                res == fetcher.ResultCancelled:
+                self.ErrorCode(ERROR_PACKAGE_DOWNLOAD_FAILED,
+                               "Failed to download %s" % item.DescURI)
+                self.Finished(EXIT_FAILED)
+                return
+            pklog.debug("Copying %s to %s ..." % (item.DestFile, dest))
+            try:
+                shutil.copy(item.DestFile, dest)
+            except Exception, e:
+                self.ErrorCode(ERROR_INTERNAL_ERROR,
+                               "Failed to copy %s to %s: %s" % (item.DestFile,
+                                                                dest, e))
+                self.Finished(EXIT_FAILED)
+                return
+        self.PercentageChanged(100)
+        pklog.debug("Sending success signal")
+        self.Finished(EXIT_SUCCESS)
+ 
+    @serialize
+    @threaded
+    @unlock_cache_afterwards
+    def doInstallPackages(self, ids):
+        '''
+        Implement the {backend}-install functionality
+        '''
+        pklog.info("Installing package with id %s" % ids)
+        if not self._lock_cache(): return
+        self.StatusChanged(STATUS_INSTALL)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        self._check_init(prange=(0,10))
+        pkgs=[]
+        for id in ids:
+            pkg = self._find_package_by_id(id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s isn't available" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            if pkg.isInstalled:
+                self.ErrorCode(ERROR_PACKAGE_ALREADY_INSTALLED,
+                               "Package %s is already installed" % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+            pkgs.append(pkg.name[:])
+            try:
+                pkg.markInstall()
+            except Exception, e:
+                self._open_cache(prange=(90,100))
+                self.ErrorCode(ERROR_UNKNOWN, "%s could not be queued for "
+                                              "installation: %s" % (pkg.name,e))
+                self.Finished(EXIT_FAILED)
+                return
+        if not self._commit_changes(): return False
+        self._open_cache(prange=(90,100))
+        self.PercentageChanged(100)
+        pklog.debug("Checking success of operation")
+        for p in pkgs:
+            if not self._cache.has_key(p) or not self._cache[p].isInstalled:
+                self.ErrorCode(ERROR_UNKNOWN, "%s was not installed" % p)
+                self.Finished(EXIT_FAILED)
+                return
+        pklog.debug("Sending success signal")
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    @unlock_cache_afterwards
+    def doInstallFiles(self, trusted, full_paths):
+        '''
+        Implement install-files for the apt backend
+        Install local Debian package files
+        '''
+        pklog.info("Installing package files: %s" % full_paths)
+        if not self._lock_cache(): return
+        self.StatusChanged(STATUS_INSTALL)
+        self.AllowCancel(False)
+        self.PercentageChanged(0)
+        self._check_init(prange=(0,10))
+        packages = []
+        # Collect all dependencies which need to be installed
+        self.StatusChanged(STATUS_DEP_RESOLVE)
+        for path in full_paths:
+            deb = apt.debfile.DebPackage(path, self._cache)
+            packages.append(deb)
+            if not deb.check():
+                self.ErrorCode(ERROR_UNKNOWN, deb._failureString)
+                self.Finished(EXIT_FAILED)
+                return
+            (install, remove, unauthenticated) = deb.requiredChanges
+            pklog.debug("Changes: Install %s, Remove %s, Unauthenticated "
+                        "%s" % (install, remove, unauthenticated))
+            if len(remove) > 0:
+                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED, 
+                               "Remove the following packages "
+                               "before: %s" % remove)
+                self.Finished(EXIT_FAILED)
+                return
+            if deb.compare_to_version_in_cache() == \
+               apt.debfile.VERSION_OUTDATED:
+                self.Message(MESSAGE_NEWER_PACKAGE_EXISTS, 
+                             "There is a later version of %s "
+                             "available in the repositories." % deb.pkgname)
+        if len(self._cache.getChanges()) > 0 and not \
+           self._commit_changes((10,25), (25,50)): 
+            return False
+        # Install the Debian package files
+        d = PackageKitDpkgInstallProgress(self)
+        try:
+            d.startUpdate()
+            d.install(full_paths)
+            d.finishUpdate()
+        except InstallTimeOutPKError, e:
+            self._recover()
+            #FIXME: should provide more information
+            self.ErrorCode(ERROR_UNKNOWN,
+                           "Transaction was cancelled since the installation "
+                           "of a package hung.\n"
+                           "This can be caused by maintainer scripts which "
+                           "require input on the terminal:\n%s" % e.message)
+            self.Finished(EXIT_KILLED)
+            return
+        except PackageManagerFailedPKError, e:
+            self._recover()
+            self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
+            self.Finished(EXIT_FAILED)
+            return
+        except Exception, e:
+            self._recover()
+            self.ErrorCode(ERROR_INTERNAL_ERROR, e.message)
+            self.Finished(EXIT_FAILED)
+            return
+        self.PercentageChanged(100)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    @unlock_cache_afterwards
+    def doRefreshCache(self, force):
+        '''
+        Implement the {backend}-refresh_cache functionality
+        '''
+        pklog.info("Refresh cache")
+        if not self._lock_cache(): return
+        self.StatusChanged(STATUS_REFRESH_CACHE)
+        self.last_action_time = time.time()
+        self.AllowCancel(False);
+        self.PercentageChanged(0)
+        self._check_init((0,10))
+        try:
+            self._cache.update(PackageKitFetchProgress(self, prange=(10,95)))
+        except Exception, e:
+            self._open_cache(prange=(95,100))
+            if self._check_canceled(): return False
+            self.ErrorCode(ERROR_UNKNOWN, "Refreshing cache failed: %s" % e)
+            self.Finished(EXIT_FAILED)
+            return
+        self._open_cache(prange=(95,100))
+        self.PercentageChanged(100)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetPackages(self, filters):
+        '''
+        Implement the apt2-get-packages functionality
+        '''
+        pklog.info("Get all packages")
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(True)
+
+        for pkg in self._cache:
+            if self._check_canceled(): return False
+            elif self._is_package_visible(pkg, filters):
+                self._emit_package(pkg)
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doResolve(self, filters, names):
+        '''
+        Implement the apt2-resolve functionality
+        '''
+        pklog.info("Resolve")
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(False)
+
+        for name in names:
+            if self._cache.has_key(name):
+                self._emit_visible_package(filters, self._cache[name])
+            else:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package name %s could not be resolved" % name)
+                self.Finished(EXIT_FAILED)
+                return
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetDepends(self, filter, ids, recursive=False):
+        '''
+        Implement the apt2-get-depends functionality
+
+        Emit all packages that need to be installed or updated to install
+        the given package ids. It behaves like a preview of the changes
+        required for the installation. An error will be emitted if the 
+        dependecies cannot be satisfied.
+        In contrast to the yum backend the whole dependency resoltions is done 
+        by the package manager. Therefor the list of satisfied packages cannot
+        be computed easily. GDebi features this. Perhaps this should be moved
+        to python-apt.
+        '''
+        pklog.info("Get depends (%s,%s,%s)" % (filter, ids, recursive))
+        #FIXME: recursive is not yet implemented
+        if recursive == True:
+            pklog.warn("Recursive dependencies are not implemented")
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(True)
+
+        # Mark all packages for installation
+        pkgs = []
+        for id in ids:
+            if self._check_canceled(): return
+            pkg = self._find_package_by_id(id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s isn't available" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            try:
+                pkg.markInstall()
+            except Exception, e:
+                #FIXME: Introduce a new info enumerate PK_INFO_MISSING for
+                #       missing dependecies
+                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+                               "Dependecies for %s cannot be satisfied: %s" % e)
+                self.Finished(EXIT_FAILED)
+                return
+            pkgs.append(pkg)
+        # Check the status of the resulting changes
+        for p in self._cache.getChanges():
+            if self._check_canceled(): return
+            if p in pkgs: continue
+            if p.markedDelete:
+                # Packagekit policy forbids removing packages for installation
+                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+                               "Remove the package %s before" % p.name)
+                self.Finished(EXIT_FAILED)
+                return
+            elif p.markedInstall or p.markedUpgrade:
+                if self._is_package_visible(p, filter):
+                    self._emit_package(p)
+            else:
+                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+                               "Please use an advanced package management tool "
+                               "e.g. Synaptic or aptitude, since there is a "
+                               "complex dependency situation.")
+                self.Finished(EXIT_FAILED)
+                return
+        # Clean up
+        self._cache.clear()
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetRequires(self, filter, ids, recursive=False):
+        '''
+        Implement the apt2-get-requires functionality
+        '''
+        pklog.info("Get requires (%s,%s,%s)" % (filter, ids, recursive))
+        #FIXME: recursive is not yet implemented
+        if recursive == True:
+            pklog.warn("Recursive dependencies are not implemented")
+        self.StatusChanged(STATUS_DEP_RESOLVE)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(True)
+        pkgs = []
+
+        # Mark all packages for installation
+        for id in ids:
+            if self._check_canceled(): return
+            pkg = self._find_package_by_id(id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s isn't available" % id)
+                self.Finished(EXIT_FAILED)
+                return
+            if pkg._pkg.Essential == True:
+                self.ErrorCode(ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE,
+                               "Package %s cannot be removed." % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+            pkgs.append(pkg)
+            try:
+                pkg.markDelete()
+            except Exception, e:
+                #FIXME: Introduce a new info enumerate PK_INFO_MISSING for
+                #       missing dependecies
+                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+                               "Error removing %s: %s" % (pkg.name, e))
+                self.Finished(EXIT_FAILED)
+                return
+        # Check the status of the resulting changes
+        for p in self._cache.getChanges():
+            if self._check_canceled(): return
+            if p.markedDelete:
+                if not p in pkgs and self._is_package_visible(p, filter):
+                    self._emit_package(p)
+            else:
+                self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+                               "Please use an advanced package management tool "
+                               "e.g. Synaptic or aptitude, since there is a "
+                               "complex dependency situation.")
+                self.Finished(EXIT_FAILED)
+                return
+        # Clean up
+        self._cache.clear()
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doWhatProvides(self, filters, provides_type, search):
+        def get_mapping_db(path):
+            """
+            Return the gdbm database at the given path or send an
+            appropriate error message
+            """
+            if not os.access(path, os.R_OK):
+                if self._cache.has_key("app-install-data") and \
+                   self._cache["app-install-data"].isInstalled == False:
+                    self.ErrorCode(ERROR_UNKNOWN,
+                                   "Please install the package "
+                                   "app-install data for a list of "
+                                   "applications that can handle files of "
+                                   "the given type")
+                else:
+                    self.ErrorCode(ERROR_UNKNOWN,
+                                   "The list of applications that can handle "
+                                   "files of the given type cannot be opened.\n"
+                                   "Try to reinstall the package "
+                                   "app-install-data.")
+                return None
+            try:
+                db = gdbm.open(path)
+            except:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "The list of applications that can handle "
+                               "files of the given type cannot be opened.\n"
+                               "Try to reinstall the package "
+                               "app-install-data.")
+                return None
+            else:
+                return db
+
+        self.StatusChanged(STATUS_QUERY)
+        self.NoPercentageUpdates()
+        self._check_init(progress=False)
+        self.AllowCancel(False)
+        if provides_type == PROVIDES_CODEC:
+            # The search term from the codec helper looks like this one:
+            match = re.match(r"gstreamer([0-9\.]+)\((.+?)\)", search)
+            if not match:
+                self.ErrorCode(ERROR_UNKNOWN,
+                               "The search term is invalid")
+                self.Finished(EXIT_FAILED)
+                return
+            codec = "%s:%s" % (match.group(1), match.group(2))
+            db = get_mapping_db("/var/cache/app-install/gai-codec-map.gdbm")
+            if db == None:
+                self.ErrorCode(ERROR_INTERNAL_ERROR,
+                               "Failed to open codec mapping database")
+                self.Finished(EXIT_FAILED)
+                return
+            if db.has_key(codec):
+                # The codec mapping db stores the packages as a string
+                # separated by spaces. Each package has its section
+                # prefixed and separated by a slash
+                # FIXME: Should make use of the section and emit a 
+                #        RepositoryRequired signal if the package does 
+                #        not exist
+                pkgs = map(lambda s: s.split("/")[1],
+                           db[codec].split(" "))
+                self._emit_visible_packages_by_name(filters, pkgs)
+        elif provides_type == PROVIDES_MIMETYPE:
+            # Emit packages that contain an application that can handle
+            # the given mime type
+            handlers = set()
+            db = get_mapping_db("/var/cache/app-install/gai-mime-map.gdbm")
+            if db == None:
+                self.Finished(EXIT_FAILED)
+                return
+            if db.has_key(search):
+                pklog.debug("Mime type is registered: %s" % db[search])
+                # The mime type handler db stores the packages as a string
+                # separated by spaces. Each package has its section
+                # prefixed and separated by a slash
+                # FIXME: Should make use of the section and emit a 
+                #        RepositoryRequired signal if the package does not exist
+                handlers = map(lambda s: s.split("/")[1],
+                               db[search].split(" "))
+                self._emit_visible_packages_by_name(filters, handlers)
+        else:
+            self.ErrorCode(ERROR_NOT_SUPPORTED,
+                           "This function is not implemented in this backend")
+            self.Finished(EXIT_FAILED)
+            return
+        self.Finished(EXIT_SUCCESS)
+
+    @serialize
+    @threaded
+    def doGetFiles(self, package_ids):
+        """
+        Emit the Files signal which includes the files included in a package
+        Apt only supports this for installed packages
+        """
+        self.StatusChanged(STATUS_INFO)
+        for id in package_ids:
+            pkg = self._find_package_by_id(id)
+            if pkg == None:
+                self.ErrorCode(ERROR_PACKAGE_NOT_FOUND,
+                               "Package %s doesn't exist" % pkg.name)
+                self.Finished(EXIT_FAILED)
+                return
+            files = string.join(self._get_installed_files(pkg), ";")
+            self.Files(id, files)
+        self.Finished(EXIT_SUCCESS)
+
+    def doSetProxy(self, http_proxy, ftp_proxy):
+        '''
+        Set a proxy server for http and ftp transfer
+        '''
+        if http_proxy:
+            pklog.debug("Set http proxy to %s" % http_proxy)
+            apt_pkg.Config.set("http::Proxy", http_proxy)
+        if ftp_proxy:
+            pklog.debug("Set ftp proxy to %s" % ftp_proxy)
+            apt_pkg.Config.set("ftp::Proxy", ftp_proxy)
+
+    def doSetLocale(self, code):
+        '''
+        Set the locale of the daemon
+
+        '''
+        #FIXME: Needs testing
+        if code != "":
+            pklog.debug("Setting language to %s" % code)
+            locale.setlocale("LANG", code)
+
+    # Helpers
+
+    def _lock_cache(self):
+        """
+        Emit an error message and return true if the apt system lock cannot
+        be acquired.
+        """
+        try:
+            apt_pkg.PkgSystemLock()
+        except SystemError:
+            self.ErrorCode(ERROR_CANNOT_GET_LOCK,
+                           "Only use one package management programme at the "
+                           "the same time.")
+            self.Finished(EXIT_FAILED)
+            return False
+        return True
+
+    def _unlock_cache(self):
+        """
+        Unlock the system package cache
+        """
+        try:
+            apt_pkg.PkgSystemUnLock()
+        except SystemError:
+            return False
+        return True
+
+    def _open_cache(self, prange=(0,100), progress=True):
+        '''
+        (Re)Open the APT cache
+        '''
+        pklog.debug("Open APT cache")
+        self.StatusChanged(STATUS_LOADING_CACHE)
+        try:
+            self._cache = PackageKitCache(PackageKitOpProgress(self, prange,
+                                                               progress))
+        except:
+            self.ErrorCode(ERROR_NO_CACHE, "Package cache could not be opened")
+            self.Finished(EXIT_FAILED)
+            self.Exit()
+            return
+        if self._cache._depcache.BrokenCount > 0:
+            self.ErrorCode(ERROR_DEP_RESOLUTION_FAILED,
+                           "There are broken dependecies on your system. "
+                           "Please use an advanced package manage e.g. "
+                           "Synaptic or aptitude to resolve this situation.")
+            self.Finished(EXIT_FAILED)
+            self.Exit()
+            return
+        self._last_cache_refresh = time.time()
+
+    def _recover(self, prange=(95,100)):
+        """
+        Try to recover from a package manager failure
+        """
+        self.StatusChanged(STATUS_CLEANUP)
+        self.NoPercentageUpdates()
+        try:
+            d = PackageKitDpkgInstallProgress(self)
+            d.startUpdate()
+            d.recover()
+            d.finishUpdate()
+        except:
+            pass
+        self._open_cache(prange)
+
+    def _commit_changes(self, fetch_range=(5,50), install_range=(50,90)):
+        """
+        Commit changes to the cache and handle errors
+        """
+        try:
+            self._cache.commit(PackageKitFetchProgress(self, fetch_range), 
+                               PackageKitInstallProgress(self, install_range))
+        except apt.cache.FetchFailedException, e:
+            self._open_cache(prange=(95,100))
+            self.ErrorCode(ERROR_PACKAGE_DOWNLOAD_FAILED, e.message)
+            self.Finished(EXIT_FAILED)
+        except apt.cache.FetchCancelledException:
+            self._open_cache(prange=(95,100))
+            self.Finished(EXIT_CANCELLED)
+            self._canceled.clear()
+        except InstallTimeOutPKError, e:
+            self._recover()
+            self._open_cache(prange=(95,100))
+            #FIXME: should provide more information
+            self.ErrorCode(ERROR_UNKNOWN,
+                           "Transaction was cancelled since the installation "
+                           "of a package hung.\n"
+                           "This can be caused by maintainer scripts which "
+                           "require input on the terminal:\n%s" % e.message)
+            self.Finished(EXIT_KILLED)
+        except PackageManagerFailedPKError, e:
+            self._recover()
+            self.ErrorCode(ERROR_UNKNOWN, "%s\n%s" % (e.message, e.output))
+            self.Finished(EXIT_FAILED)
+        else:
+            return True
+        return False
+
+    def _check_init(self, prange=(0,10), progress=True):
+        '''
+        Check if the backend was initialized well and try to recover from
+        a broken setup
+        '''
+        pklog.debug("Checking apt cache and xapian database")
+        pkg_cache = os.path.join(apt_pkg.Config["Dir"],
+                                 apt_pkg.Config["Dir::Cache"],
+                                 apt_pkg.Config["Dir::Cache::pkgcache"])
+        src_cache = os.path.join(apt_pkg.Config["Dir"],
+                                 apt_pkg.Config["Dir::Cache"],
+                                 apt_pkg.Config["Dir::Cache::srcpkgcache"])
+        # Check if the cache instance is of the coorect class type, contains
+        # any broken packages and if the dpkg status or apt cache files have 
+        # been changed since the last refresh
+        if not isinstance(self._cache, apt.cache.Cache) or \
+           (self._cache._depcache.BrokenCount > 0) or \
+           (os.stat(apt_pkg.Config["Dir::State::status"])[stat.ST_MTIME] > \
+            self._last_cache_refresh) or \
+           (os.stat(pkg_cache)[stat.ST_MTIME] > self._last_cache_refresh) or \
+           (os.stat(src_cache)[stat.ST_MTIME] > self._last_cache_refresh):
+            pklog.debug("Reloading the cache is required")
+            self._open_cache(prange, progress)
+        else:
+            self._cache.clear()
+
+    def _check_canceled(self):
+        '''
+        Check if the current transaction was canceled. If so send the
+        corresponding error message and return True
+        '''
+        if self._canceled.isSet():
+            self.Finished(EXIT_CANCELLED)
+            self._canceled.clear()
+            return True
+        return False
+ 
+    def get_id_from_package(self, pkg, force_candidate=False):
+        '''
+        Return the packagekit id of package. By default this will be the 
+        installed version for installed packages and the candidate version
+        for not installed packages.
+
+        The force_candidate option will also report the id of the candidate
+        version for installed packages.
+        '''
+        origin = ""
+        cand_origin = pkg.candidateOrigin
+        if not pkg.isInstalled or force_candidate:
+            version = pkg.candidateVersion
+            if cand_origin:
+                origin = cand_origin[0].label
+        else:
+            version = pkg.installedVersion
+            if cand_origin and cand_origin[0].site != "" and \
+               pkg.installedVersion == pkg.candidateVersion:
+                origin = cand_origin[0].label
+        id = self._get_package_id(pkg.name, version, pkg.architecture, origin)
+        return id
+
+    def _emit_package(self, pkg, info=None, force_candidate=False):
+        '''
+        Send the Package signal for a given apt package
+        '''
+        id = self.get_id_from_package(pkg, force_candidate)
+        section = pkg.section.split("/")[-1]
+        if info == None:
+            if pkg.isInstalled:
+                if section == "metapackages":
+                    info = INFO_COLLECTION_INSTALLED
+                else:
+                    info = INFO_INSTALLED
+            else:
+                if section == "metapackages":
+                    info = INFO_COLLECTION_AVAILABLE
+                else:
+                    info = INFO_AVAILABLE
+        summary = pkg.summary
+        self.Package(info, id, summary)
+
+    def _emit_visible_package(self, filters, pkg, info=None):
+        """
+        Filter and emit a package
+        """
+        if self._is_package_visible(pkg, filters):
+            self._emit_package(pkg, info)
+
+    def _emit_visible_packages(self, filters, pkgs, info=None):
+        """
+        Filter and emit packages
+        """
+        for p in pkgs:
+            if self._is_package_visible(p, filters):
+                self._emit_package(p, info)
+
+    def _emit_visible_packages_by_name(self, filters, pkgs, info=None):
+        """
+        Find the packages with the given namens. Afterwards filter and emit
+        them
+        """
+        for name in pkgs:
+            if self._cache.has_key(name) and \
+               self._is_package_visible(self._cache[name], filters):
+                self._emit_package(self._cache[name], info)
+
+
+    def _is_package_visible(self, pkg, filters):
+        '''
+        Return True if the package should be shown in the user interface
+        '''
+        if filters == FILTER_NONE:
+            return True
+        for filter in filters.split(";"):
+            if (filter == FILTER_INSTALLED and not pkg.isInstalled) or \
+               (filter == FILTER_NOT_INSTALLED and pkg.isInstalled) or \
+               (filter == FILTER_SUPPORTED and not \
+                self._is_package_supported(pkg)) or \
+               (filter == FILTER_NOT_SUPPORTED and \
+                self._is_package_supported(pkg)) or \
+               (filter == FILTER_FREE and not self._is_package_free(pkg)) or \
+               (filter == FILTER_NOT_FREE and \
+                not self._is_package_not_free(pkg)) or \
+               (filter == FILTER_GUI and not self._has_package_gui(pkg)) or \
+               (filter == FILTER_NOT_GUI and self._has_package_gui(pkg)) or \
+               (filter == FILTER_COLLECTIONS and not \
+                self._is_package_collection(pkg)) or \
+               (filter == FILTER_NOT_COLLECTIONS and \
+                self._is_package_collection(pkg)) or\
+                (filter == FILTER_DEVELOPMENT and not \
+                self._is_package_devel(pkg)) or \
+               (filter == FILTER_NOT_DEVELOPMENT and \
+                self._is_package_devel(pkg)):
+                return False
+        return True
+
+    def _is_package_not_free(self, pkg):
+        """
+        Return True if we can be sure that the package's license isn't any 
+        free one
+        """
+        candidate = pkg.candidateOrigin
+        return candidate != None and \
+               ((candidate[0].origin == "Ubuntu" and \
+                 candidate[0].component in ["multiverse", "restricted"]) or \
+                (candidate[0].origin == "Debian" and \
+                 candidate[0].component in ["contrib", "non-free"])) and \
+               candidate[0].trusted == True
+
+    def _is_package_collection(self, pkg):
+        """
+        Return True if the package is a metapackge
+        """
+        section = pkg.section.split("/")[-1]
+        return section == "metapackages"
+
+    def _is_package_free(self, pkg):
+        """
+        Return True if we can be sure that the package has got a free license
+        """
+        candidate = pkg.candidateOrigin
+        return candidate != None and \
+               ((candidate[0].origin == "Ubuntu" and \
+                 candidate[0].component in ["main", "universe"]) or \
+                (candidate[0].origin == "Debian" and \
+                 candidate[0].component == "main")) and\
+               candidate[0].trusted == True
+
+    def _has_package_gui(self, pkg):
+        #FIXME: should go to a modified Package class
+        #FIXME: take application data into account. perhaps checking for
+        #       property in the xapian database
+        return pkg.section.split('/')[-1].lower() in ['x11', 'gnome', 'kde']
+
+    def _is_package_devel(self, pkg):
+        #FIXME: should go to a modified Package class
+        return pkg.name.endswith("-dev") or pkg.name.endswith("-dbg") or \
+               pkg.section.split('/')[-1].lower() in ['devel', 'libdevel']
+
+    def _is_package_supported(self, pkg):
+        candidate = pkg.candidateOrigin[0]
+        return candidate != None and \
+               candidate[0].origin == "Ubuntu" and \
+               candidate[0].component in ["main", "restricted"] and \
+               candidate[0].trusted == True
+
+    def _find_package_by_id(self, id):
+        '''
+        Return a package matching to the given package id
+        '''
+        # FIXME: Perform more checks
+        name, version, arch, data = self.get_package_from_id(id)
+        if self._cache.has_key(name):
+            return self._cache[name]
+        else:
+            return None
+
+    def _get_installed_files(self, pkg):
+        """
+        Return the list of unicode names of the files which have
+        been installed by the package
+
+        This method should be obsolete by the apt.package.Package.installedFiles
+        attribute as soon as the consolidate branch of python-apt gets merged
+        """
+        path = os.path.join(apt_pkg.Config["Dir"],
+                            "var/lib/dpkg/info/%s.list" % pkg.name)
+        try:
+            list = open(path)
+            files = list.read().decode().split("\n")
+            list.close()
+        except:
+            return []
+        return files
+
+    def _get_changelog(self, pkg, uri=None, cancel_lock=None):
+        """
+        Download the changelog of the package and return it as unicode 
+        string
+
+        This method is already part of the consolidate branch of python-apt
+
+        uri: Is the uri to the changelog file. The following named variables
+             will be substituted: src_section, prefix, src_pkg and src_ver
+             For example the Ubuntu changelog:
+             uri = "http://changelogs.ubuntu.com/changelogs/pool" \\
+                   "/%(src_section)s/%(prefix)s/%(src_pkg)s" \\
+                   "/%(src_pkg)s_%(src_ver)s/changelog"
+        cancel_lock: If this threading.Lock() is set, the download will be
+                     canceled
+        """
+        if uri == None:
+            if pkg.candidateOrigin[0].origin == "Debian":
+                uri = "http://packages.debian.org/changelogs/pool" \
+                      "/%(src_section)s/%(prefix)s/%(src_pkg)s" \
+                      "/%(src_pkg)s_%(src_ver)s/changelog"
+            elif pkg.candidateOrigin[0].origin == "Ubuntu":
+                uri = "http://changelogs.ubuntu.com/changelogs/pool" \
+                      "/%(src_section)s/%(prefix)s/%(src_pkg)s" \
+                      "/%(src_pkg)s_%(src_ver)s/changelog"
+            else:
+                return "The list of changes is not available"
+
+        # get the src package name
+        src_pkg = pkg.sourcePackageName
+
+        # assume "main" section 
+        src_section = "main"
+        # use the section of the candidate as a starting point
+        section = pkg._depcache.GetCandidateVer(pkg._pkg).Section
+
+        # get the source version, start with the binaries version
+        bin_ver = pkg.candidateVersion
+        src_ver = pkg.candidateVersion
+        #print "bin: %s" % binver
+        try:
+            # try to get the source version of the pkg, this differs
+            # for some (e.g. libnspr4 on ubuntu)
+            # this feature only works if the correct deb-src are in the 
+            # sources.list
+            # otherwise we fall back to the binary version number
+            src_records = apt_pkg.GetPkgSrcRecords()
+            src_rec = src_records.Lookup(src_pkg)
+            if src_rec:
+                src_ver = src_records.Version
+                #if apt_pkg.VersionCompare(binver, srcver) > 0:
+                #    srcver = binver
+                if not src_ver:
+                    src_ver = bin_ver
+                #print "srcver: %s" % src_ver
+                section = src_records.Section
+                #print "srcsect: %s" % section
+            else:
+                # fail into the error handler
+                raise SystemError
+        except SystemError, e:
+            src_ver = bin_ver
+
+        l = section.split("/")
+        if len(l) > 1:
+            src_section = l[0]
+
+        # lib is handled special
+        prefix = src_pkg[0]
+        if src_pkg.startswith("lib"):
+            prefix = "lib" + src_pkg[3]
+
+        # stip epoch
+        l = src_ver.split(":")
+        if len(l) > 1:
+            src_ver = "".join(l[1:])
+
+        uri = uri % {"src_section" : src_section,
+                     "prefix" : prefix,
+                     "src_pkg" : src_pkg,
+                     "src_ver" : src_ver}
+        try:
+            # Check if the download was canceled
+            if cancel_lock and cancel_lock.isSet(): return ""
+            changelog_file = urllib2.urlopen(uri)
+            # do only get the lines that are new
+            changelog = ""
+            regexp = "^%s \((.*)\)(.*)$" % (re.escape(src_pkg))
+
+            i=0
+            while True:
+                # Check if the download was canceled
+                if cancel_lock and cancel_lock.isSet(): return ""
+                # Read changelog line by line
+                line_raw = changelog_file.readline()
+                if line_raw == "":
+                    break
+                # The changelog is encoded in utf-8, but since there isn't any
+                # http header, urllib2 seems to treat it as ascii
+                line = line_raw.decode("utf-8")
+
+                #print line.encode('utf-8')
+                match = re.match(regexp, line)
+                if match:
+                    # strip epoch from installed version
+                    # and from changelog too
+                    installed = pkg.installedVersion
+                    if installed and ":" in installed:
+                        installed = installed.split(":",1)[1]
+                    changelog_ver = match.group(1)
+                    if changelog_ver and ":" in changelog_ver:
+                        changelog_ver = changelog_ver.split(":", 1)[1]
+                    if installed and \
+                        apt_pkg.VersionCompare(changelog_ver, installed) <= 0:
+                        break
+                # EOF (shouldn't really happen)
+                changelog += line
+
+            # Print an error if we failed to extract a changelog
+            if len(changelog) == 0:
+                changelog = "The list of changes is not available"
+        except urllib2.HTTPError,e:
+            return "The list of changes is not available yet.\n\n" \
+                    "Please use http://launchpad.net/ubuntu/+source/%s/%s/" \
+                    "+changelog\n" \
+                    "until the changes become available or try again " \
+                    "later." % (src_pkg, src_ver)
+        except IOError, httplib.BadStatusLine:
+            return "Failed to download the list of changes.\nPlease " \
+                   "check your Internet connection."
+        return changelog
+
+    def _get_package_group(self, pkg):
+        """
+        Return the packagekit group corresponding to the package's section
+        """
+        section = pkg.section.split("/")[-1]
+        if SECTION_GROUP_MAP.has_key(section):
+            return SECTION_GROUP_MAP[section]
+        else:
+            pklog.debug("Unkown package section %s of %s" % (pkg.section,
+                                                             pkg.name))
+            return GROUP_UNKNOWN
+
+    def _get_package_description(self, pkg):
+        """
+        Return the formated long description according to the Debian policy
+        (Chapter 5.6.13).
+        See http://www.debian.org/doc/debian-policy/ch-controlfields.html
+        for more information.
+        """
+        if not pkg._lookupRecord():
+            return ""
+        # get the translated description
+        ver = pkg._depcache.GetCandidateVer(pkg._pkg)
+        desc_iter = ver.TranslatedDescription
+        pkg._records.Lookup(desc_iter.FileList.pop(0))
+        desc = ""
+        try:
+            s = unicode(pkg._records.LongDesc,"utf-8")
+        except UnicodeDecodeError,e:
+            s = "Invalid unicode in description for '%s' (%s)" % (pkg.name, e)
+        lines = string.split(s, "\n")
+        for i in range(len(lines)):
+            # Skip the first line, since its a duplication of the summary
+            if i == 0: continue
+            raw_line = lines[i]
+            if raw_line.strip() == ".":
+                # The line is just line break
+                if not desc.endswith("\n"):
+                    desc += "\n"
+                continue
+            elif raw_line.startswith("  "):
+                # The line should be displayed verbatim without word wrapping
+                if not desc.endswith("\n"):
+                    line = "\n%s\n" % raw_line[2:]
+                else:
+                    line = "%s\n" % raw_line[2:]
+            elif raw_line.startswith(" "):
+                # The line is part of a paragraph.
+                if desc.endswith("\n") or desc == "":
+                    # Skip the leading white space
+                    line = raw_line[1:]
+                else:
+                    line = raw_line
+            else:
+                line = raw_line
+                pklog.debug("invalid line %s in description for %s:\n%s" % \
+                            (i, pkg.name, pkg.rawDescription))
+            # Use dots for lists
+            line = re.sub(r"^(\s*)(\*|0|o|-) ", ur"\1\u2022 ", line, 1)
+            # Add current line to the description
+            desc += line
+        return desc
+
+
+def sigquit(signum, frame):
+    pklog.error("Was killed")
+    sys.exit(1)
+
+def debug_exception(type, value, tb):
+    """
+    Provides an interactive debugging session on unhandled exceptions
+    See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65287
+    """
+    if hasattr(sys, 'ps1') or not sys.stderr.isatty() or \
+       not sys.stdin.isatty() or not sys.stdout.isatty() or type==SyntaxError:
+        # Calls the default handler in interactive mode, if output is·
+        # redirected or on syntax errors
+        sys.__excepthook__(type, value, tb)
+    else:
+        import traceback, pdb
+        traceback.print_exception(type, value, tb)
+        print
+        pdb.pm()
+
+def takeover():
+    """
+    Exit the currently running backend
+    """
+    PACKAGEKIT_DBUS_SERVICE = 'org.freedesktop.PackageKitAptBackend'
+    PACKAGEKIT_DBUS_INTERFACE = 'org.freedesktop.PackageKitBackend'
+    PACKAGEKIT_DBUS_PATH = '/org/freedesktop/PackageKitBackend'
+    try:
+        bus = dbus.SystemBus()
+    except dbus.DBusException, e:
+        pklog.critical("Unable to connect to dbus: %s" % e)
+        sys.exit(1)
+    proxy = bus.get_object(PACKAGEKIT_DBUS_SERVICE, PACKAGEKIT_DBUS_PATH)
+    iface = dbus.Interface(proxy, PACKAGEKIT_DBUS_INTERFACE)
+    try:
+        iface.Exit()
+    except dbus.DBusException:
+        pass
+
+def run():
+    """
+    Start the apt backend
+    """
+    loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+    bus = dbus.SystemBus(mainloop=loop)
+    bus_name = dbus.service.BusName(PACKAGEKIT_DBUS_SERVICE, bus=bus)
+    manager = PackageKitAptBackend(bus_name, PACKAGEKIT_DBUS_PATH)
+    manager.run()
+
+def main():
+    parser = optparse.OptionParser(description="APT backend for PackageKit")
+    parser.add_option("-t", "--takeover",
+                      action="store_true", dest="takeover",
+                      help="Exit the currently running backend "
+                           "(Only needed by developers)")
+    parser.add_option("-r", "--root",
+                      action="store", type="string", dest="root",
+                      help="Use the given directory as the system root "
+                           "(Only needed by developers)")
+    parser.add_option("-p", "--profile",
+                      action="store", type="string", dest="profile",
+                      help="Store profiling stats in the given file "
+                           "(Only needed by developers)")
+    parser.add_option("-d", "--debug",
+                      action="store_true", dest="debug",
+                      help="Show a lot of additional information and drop to "
+                           "a debugging console on unhandled exceptions "
+                           "(Only needed by developers)")
+    (options, args) = parser.parse_args()
+    if options.debug:
+        pklog.setLevel(logging.DEBUG)
+        sys.excepthook = debug_exception
+
+    if options.root:
+        config = apt_pkg.Config
+        config.Set("Dir", options.root)
+        config.Set("Dir::State::status",
+                   os.path.join(options.root, "/var/lib/dpkg/status"))
+
+    if options.takeover:
+        takeover()
+
+    if options.profile:
+        import hotshot
+        prof = hotshot.Profile(options.profile)
+        prof.runcall(run)
+        prof.close()
+    else:
+        run()
+
+if __name__ == '__main__':
+    main()
+
+# vim: ts=4 et sts=4
diff --git a/backends/apt/pk-backend-apt.py b/backends/apt/pk-backend-apt.py
new file mode 100644
index 0000000..0b057d8
--- /dev/null
+++ b/backends/apt/pk-backend-apt.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+pk-backend-apt - Runs the PackageKit apt backend
+"""
+# Copyright (C) 2008 Sebastian Heinlein <devel at glatzor.de>
+#
+# 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
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+__author__  = "Sebastian Heinlein <devel at glatzor.de>"
+
+from packagekit.aptbackend import main
+
+main()
+
+# vim:ts=4:sw=4:et
diff --git a/data/org.freedesktop.PackageKitAptBackend.service.in b/data/org.freedesktop.PackageKitAptBackend.service.in
index 2e3d5d5..9326019 100644
--- a/data/org.freedesktop.PackageKitAptBackend.service.in
+++ b/data/org.freedesktop.PackageKitAptBackend.service.in
@@ -1,5 +1,5 @@
 [D-BUS Service]
 Name=org.freedesktop.PackageKitAptBackend
-Exec=@servicedir@/aptDBUSBackend.py
+Exec=@servicedir@/pk-backend-apt.py
 User=@PK_BACKEND_USER@
 
commit 101a40ec584c7cc1f1df3bb5146096c86c3c5a47
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 9 05:42:53 2009 +0100

    APT: Fix an API change in debfile

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index 88ae820..700c325 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -1261,7 +1261,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         for path in full_paths:
             deb = apt.debfile.DebPackage(path, self._cache)
             packages.append(deb)
-            if not deb.checkDeb():
+            if not deb.check():
                 self.ErrorCode(ERROR_UNKNOWN, deb._failureString)
                 self.Finished(EXIT_FAILED)
                 return
commit 550c71f2bceac89440de6944724731c501136984
Author: Sebastian Heinlein <devel at glatzor.de>
Date:   Mon Feb 9 05:35:46 2009 +0100

    APT: Use the merged debfile module of python-apt

diff --git a/backends/apt/aptDBUSBackend.py b/backends/apt/aptDBUSBackend.py
index f8b93b2..88ae820 100755
--- a/backends/apt/aptDBUSBackend.py
+++ b/backends/apt/aptDBUSBackend.py
@@ -40,6 +40,7 @@ import urllib2
 import warnings
 
 import apt
+import apt.debfile
 import apt_pkg
 import dbus
 import dbus.glib
@@ -50,7 +51,6 @@ import gobject
 from packagekit.daemonBackend import PACKAGEKIT_DBUS_INTERFACE, PACKAGEKIT_DBUS_PATH, PackageKitBaseBackend, PackagekitProgress, pklog, threaded, serialize
 from packagekit.enums import *
 
-import debfile
 
 warnings.filterwarnings(action='ignore', category=FutureWarning)
 
@@ -250,6 +250,7 @@ class DpkgInstallProgress(apt.progress.InstallProgress):
     """
     Class to initiate and monitor installation of local package files with dpkg
     """
+    #FIXME: Use the merged DpkgInstallProgress of python-apt
     def recover(self):
         """
         Run "dpkg --configure -a"
@@ -1258,7 +1259,7 @@ class PackageKitAptBackend(PackageKitBaseBackend):
         # Collect all dependencies which need to be installed
         self.StatusChanged(STATUS_DEP_RESOLVE)
         for path in full_paths:
-            deb = debfile.DebPackage(path, self._cache)
+            deb = apt.debfile.DebPackage(path, self._cache)
             packages.append(deb)
             if not deb.checkDeb():
                 self.ErrorCode(ERROR_UNKNOWN, deb._failureString)
@@ -1273,14 +1274,15 @@ class PackageKitAptBackend(PackageKitBaseBackend):
                                "before: %s" % remove)
                 self.Finished(EXIT_FAILED)
                 return
-            if deb.compareToVersionInCache() == debfile.VERSION_OUTDATED:
+            if deb.compare_to_version_in_cache() == \
+               apt.debfile.VERSION_OUTDATED:
                 self.Message(MESSAGE_NEWER_PACKAGE_EXISTS, 
                              "There is a later version of %s "
                              "available in the repositories." % deb.pkgname)
         if len(self._cache.getChanges()) > 0 and not \
            self._commit_changes((10,25), (25,50)): 
             return False
-       # Install the Debian package files
+        # Install the Debian package files
         d = PackageKitDpkgInstallProgress(self)
         try:
             d.startUpdate()
diff --git a/backends/apt/debfile.py b/backends/apt/debfile.py
deleted file mode 100644
index 6e664da..0000000
--- a/backends/apt/debfile.py
+++ /dev/null
@@ -1,536 +0,0 @@
-# Copyright (c) 2005-2007 Canonical
-#
-# AUTHOR:
-# Michael Vogt <mvo at ubuntu.com>
-#
-# This file is part of GDebi
-#
-# GDebi 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.
-#
-# GDebi 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 GDebi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#
-
-import warnings
-warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
-import apt_inst, apt_pkg
-import sys
-import os
-from gettext import gettext as _
-
-# Constants for comparing the local package file with the version in the cache
-(VERSION_NONE,
- VERSION_OUTDATED,
- VERSION_SAME,
- VERSION_NEWER) = range(4)
- 
-class NoDebArchiveException(IOError):
-    pass
-
-class DebPackage(object):
-
-    _supported_data_members = ("data.tar.gz", "data.tar.bz2", "data.tar.lzma")
-
-    debug = 0
-
-    def __init__(self, filename=None, cache=None):
-        self._cache = cache
-        self.file = filename
-        self._needPkgs = []
-        self._sections = {}
-        self._installedConflicts = set()
-        self._failureString = ""
-        if filename:
-            self.open(filename)
-
-    def open(self, filename):
-        " open given debfile "
-        self.filename = filename
-        if not apt_inst.arCheckMember(open(self.filename), "debian-binary"):
-            raise NoDebArchiveException, "This is not a valid DEB archive, missing '%s' member" % "debian-binary"
-        control = apt_inst.debExtractControl(open(self.filename))
-        self._sections = apt_pkg.ParseSection(control)
-        self.pkgname = self._sections["Package"]
-
-    def __getitem__(self, key):
-        return self._sections[key]
-        
-    def filelist(self):
-        """ return the list of files in the deb """
-        files = []
-        def extract_cb(What,Name,Link,Mode,UID,GID,Size,MTime,Major,Minor):
-            #print "%s '%s','%s',%u,%u,%u,%u,%u,%u,%u"\
-            #      % (What,Name,Link,Mode,UID,GID,Size, MTime, Major, Minor)
-            files.append(Name)
-        for member in self._supported_data_members:
-            if apt_inst.arCheckMember(open(self.filename), member):
-                try:
-                    apt_inst.debExtract(open(self.filename), extract_cb, member)
-                    break
-                except SystemError, e:
-                    return ["List of files for '%s'could not be read" % self.filename]
-        return files
-    filelist = property(filelist)
-
-    def _isOrGroupSatisfied(self, or_group):
-        """ this function gets a 'or_group' and analyzes if
-            at least one dependency of this group is already satisfied """
-        self._dbg(2,"_checkOrGroup(): %s " % (or_group))
-
-        for dep in or_group:
-            depname = dep[0]
-            ver = dep[1]
-            oper = dep[2]
-
-            # check for virtual pkgs
-            if not self._cache.has_key(depname):
-                if self._cache.isVirtualPackage(depname):
-                    self._dbg(3,"_isOrGroupSatisfied(): %s is virtual dep" % depname)
-                    for pkg in self._cache.getProvidingPackages(depname):
-                        if pkg.isInstalled:
-                            return True
-                continue
-
-            inst = self._cache[depname]
-            instver = inst.installedVersion
-            if instver != None and apt_pkg.CheckDep(instver,oper,ver) == True:
-                return True
-        return False
-            
-
-    def _satisfyOrGroup(self, or_group):
-        """ try to satisfy the or_group """
-
-        or_found = False
-        virtual_pkg = None
-
-        for dep in or_group:
-            depname = dep[0]
-            ver = dep[1]
-            oper = dep[2]
-
-            # if we don't have it in the cache, it may be virtual
-            if not self._cache.has_key(depname):
-                if not self._cache.isVirtualPackage(depname):
-                    continue
-                providers = self._cache.getProvidingPackages(depname)
-                # if a package just has a single virtual provider, we
-                # just pick that (just like apt)
-                if len(providers) != 1:
-                    continue
-                depname = providers[0].name
-                
-            # now check if we can satisfy the deps with the candidate(s)
-            # in the cache
-            cand = self._cache[depname]
-            candver = self._cache._depcache.GetCandidateVer(cand._pkg)
-            if not candver:
-                continue
-            if not apt_pkg.CheckDep(candver.VerStr,oper,ver):
-                continue
-
-            # check if we need to install it
-            self._dbg(2,"Need to get: %s" % depname)
-            self._needPkgs.append(depname)
-            return True
-
-        # if we reach this point, we failed
-        or_str = ""
-        for dep in or_group:
-            or_str += dep[0]
-            if dep != or_group[len(or_group)-1]:
-                or_str += "|"
-        self._failureString +="Dependency is not satisfiable: %s\n" % or_str
-        return False
-
-    def _checkSinglePkgConflict(self, pkgname, ver, oper):
-        """ returns true if a pkg conflicts with a real installed/marked
-            pkg """
-        # FIXME: deal with conflicts against its own provides
-        #        (e.g. Provides: ftp-server, Conflicts: ftp-server)
-        self._dbg(3, "_checkSinglePkgConflict() pkg='%s' ver='%s' oper='%s'" % (pkgname, ver, oper))
-        pkgver = None
-        cand = self._cache[pkgname]
-        if cand.isInstalled:
-            pkgver = cand.installedVersion
-        elif cand.markedInstall:
-            pkgver = cand.candidateVersion
-        #print "pkg: %s" % pkgname
-        #print "ver: %s" % ver
-        #print "pkgver: %s " % pkgver
-        #print "oper: %s " % oper
-        if (pkgver and apt_pkg.CheckDep(pkgver,oper,ver) and 
-            not self.replacesRealPkg(pkgname, oper, ver)):
-            self._failureString += "Conflicts with the installed package '%s'" % cand.name
-            return True
-        return False
-
-    def _checkConflictsOrGroup(self, or_group):
-        """ check the or-group for conflicts with installed pkgs """
-        self._dbg(2,"_checkConflictsOrGroup(): %s " % (or_group))
-
-        or_found = False
-        virtual_pkg = None
-
-        for dep in or_group:
-            depname = dep[0]
-            ver = dep[1]
-            oper = dep[2]
-
-            # check conflicts with virtual pkgs
-            if not self._cache.has_key(depname):
-                # FIXME: we have to check for virtual replaces here as 
-                #        well (to pass tests/gdebi-test8.deb)
-                if self._cache.isVirtualPackage(depname):
-                    for pkg in self._cache.getProvidingPackages(depname):
-                        self._dbg(3, "conflicts virtual check: %s" % pkg.name)
-                        # P/C/R on virtal pkg, e.g. ftpd
-                        if self.pkgName == pkg.name:
-                            self._dbg(3, "conflict on self, ignoring")
-                            continue
-                        if self._checkSinglePkgConflict(pkg.name,ver,oper):
-                            self._installedConflicts.add(pkg.name)
-                continue
-            if self._checkSinglePkgConflict(depname,ver,oper):
-                self._installedConflicts.add(depname)
-        return len(self._installedConflicts) != 0
-
-    def getConflicts(self):
-        """
-        Return list of package names conflicting with this package.
-
-        WARNING: This method will is deprecated. Please use the 
-        attribute DebPackage.depends instead.
-        """
-        return self.conflicts
-
-    def conflicts(self):
-        """
-        List of package names conflicting with this package
-        """
-        conflicts = []
-        key = "Conflicts"
-        if self._sections.has_key(key):
-            conflicts = apt_pkg.ParseDepends(self._sections[key])
-        return conflicts
-    conflicts = property(conflicts)
-
-    def getDepends(self):
-        """
-        Return list of package names on which this package depends on.
-
-        WARNING: This method will is deprecated. Please use the 
-        attribute DebPackage.depends instead.
-        """
-        return self.depends
-
-    def depends(self):
-        """
-        List of package names on which this package depends on
-        """
-        depends = []
-        # find depends
-        for key in ["Depends","PreDepends"]:
-            if self._sections.has_key(key):
-                depends.extend(apt_pkg.ParseDepends(self._sections[key]))
-        return depends
-    depends = property(depends)
-
-    def getProvides(self):
-        """
-        Return list of virtual packages which are provided by this package.
-
-        WARNING: This method will is deprecated. Please use the 
-        attribute DebPackage.provides instead.
-        """
-        return self.provides
-
-    def provides(self):
-        """
-        List of virtual packages which are provided by this package
-        """
-        provides = []
-        key = "Provides"
-        if self._sections.has_key(key):
-            provides = apt_pkg.ParseDepends(self._sections[key])
-        return provides
-    provides = property(provides)
-
-    def getReplaces(self):
-        """
-        Return list of packages which are replaced by this package.
-
-        WARNING: This method will is deprecated. Please use the 
-        attribute DebPackage.replaces instead.
-        """
-        return self.replaces
-
-    def replaces(self):
-        """
-        List of packages which are replaced by this package
-        """
-        replaces = []
-        key = "Replaces"
-        if self._sections.has_key(key):
-            replaces = apt_pkg.ParseDepends(self._sections[key])
-        return replaces
-    replaces = property(replaces)
-
-    def replacesRealPkg(self, pkgname, oper, ver):
-        """ 
-        return True if the deb packages replaces a real (not virtual)
-        packages named pkgname, oper, ver 
-        """
-        self._dbg(3, "replacesPkg() %s %s %s" % (pkgname,oper,ver))
-        pkgver = None
-        cand = self._cache[pkgname]
-        if cand.isInstalled:
-            pkgver = cand.installedVersion
-        elif cand.markedInstall:
-            pkgver = cand.candidateVersion
-        for or_group in self.getReplaces():
-            for (name, ver, oper) in or_group:
-                if (name == pkgname and 
-                    apt_pkg.CheckDep(pkgver,oper,ver)):
-                    self._dbg(3, "we have a replaces in our package for the conflict against '%s'" % (pkgname))
-                    return True
-        return False
-
-    def checkConflicts(self):
-        """ check if the pkg conflicts with a existing or to be installed
-            package. Return True if the pkg is ok """
-        res = True
-        for or_group in self.getConflicts():
-            if self._checkConflictsOrGroup(or_group):
-                #print "Conflicts with a exisiting pkg!"
-                #self._failureString = "Conflicts with a exisiting pkg!"
-                res = False
-        return res
-
-   
-    def compareToVersionInCache(self, useInstalled=True):
-        """ checks if the pkg is already installed or availabe in the cache
-            and if so in what version, returns if the version of the deb
-            is not available,older,same,newer
-        """
-        self._dbg(3,"compareToVersionInCache")
-        pkgname = self._sections["Package"]
-        debver = self._sections["Version"]
-        self._dbg(1,"debver: %s" % debver)
-        if self._cache.has_key(pkgname):
-            if useInstalled:
-                cachever = self._cache[pkgname].installedVersion
-            else:
-                cachever = self._cache[pkgname].candidateVersion
-            if cachever != None:
-                cmp = apt_pkg.VersionCompare(cachever,debver)
-                self._dbg(1, "CompareVersion(debver,instver): %s" % cmp)
-                if cmp == 0:
-                    return VERSION_SAME
-                elif cmp < 0:
-                    return VERSION_NEWER
-                elif cmp > 0:
-                    return VERSION_OUTDATED
-        return VERSION_NONE
-
-    def checkDeb(self):
-        self._dbg(3,"checkDepends")
-
-        # check arch
-        arch = self._sections["Architecture"]
-        if  arch != "all" and arch != apt_pkg.Config.Find("APT::Architecture"):
-            self._dbg(1,"ERROR: Wrong architecture dude!")
-            self._failureString = "Wrong architecture '%s'" % arch
-            return False
-
-        # check version
-        res = self.compareToVersionInCache()
-        if res == VERSION_OUTDATED: # the deb is older than the installed
-            self._failureString = "A later version is already installed"
-            return False
-
-        # FIXME: this sort of error handling sux
-        self._failureString = ""
-
-        # check conflicts
-        if not self.checkConflicts():
-            return False
-
-        # try to satisfy the dependencies
-        res = self._satisfyDepends(self.getDepends())
-        if not res:
-            return False
-
-        # check for conflicts again (this time with the packages that are
-        # makeed for install)
-        if not self.checkConflicts():
-            return False
-
-        if self._cache._depcache.BrokenCount > 0:
-            self._failureString = "Failed to satisfy all dependencies (broken cache)"
-            # clean the cache again
-            self._cache.clear()
-            return False
-        return True
-
-    def satisfyDependsStr(self, dependsstr):
-        return self._satisfyDepends(apt_pkg.ParseDepends(dependsstr))
-
-    def _satisfyDepends(self, depends):
-        # turn off MarkAndSweep via a action group (if available)
-        try:
-            _actiongroup = apt_pkg.GetPkgActionGroup(self._cache._depcache)
-        except AttributeError, e:
-            pass
-        # check depends
-        for or_group in depends:
-            #print "or_group: %s" % or_group
-            #print "or_group satified: %s" % self._isOrGroupSatisfied(or_group)
-            if not self._isOrGroupSatisfied(or_group):
-                if not self._satisfyOrGroup(or_group):
-                    return False
-        # now try it out in the cache
-            for pkg in self._needPkgs:
-                try:
-                    self._cache[pkg].markInstall(fromUser=False)
-                except SystemError, e:
-                    self._failureString = "Cannot install '%s'" % pkg
-                    self._cache.clear()
-                    return False
-        return True
-
-    def missingDeps(self):
-        self._dbg(1, "Installing: %s" % self._needPkgs)
-        if self._needPkgs == None:
-            self.checkDeb()
-        return self._needPkgs
-    missingDeps = property(missingDeps)
-
-    def requiredChanges(self):
-        """ gets the required changes to satisfy the depends.
-            returns a tuple with (install, remove, unauthenticated)
-        """
-        install = []
-        remove = []
-        unauthenticated = []
-        for pkg in self._cache:
-            if pkg.markedInstall or pkg.markedUpgrade:
-                install.append(pkg.name)
-                # check authentication, one authenticated origin is enough
-                # libapt will skip non-authenticated origins then
-                authenticated = False
-                for origin in pkg.candidateOrigin:
-                    authenticated |= origin.trusted
-                if not authenticated:
-                    unauthenticated.append(pkg.name)
-            if pkg.markedDelete:
-                remove.append(pkg.name)
-        return (install,remove, unauthenticated)
-    requiredChanges = property(requiredChanges)
-
-    def _dbg(self, level, msg):
-        """Write debugging output to sys.stderr.
-        """
-        if level <= self.debug:
-            print >> sys.stderr, msg
-
-    def install(self, installProgress=None):
-        """ Install the package """
-        if installProgress == None:
-            res = os.system("/usr/sbin/dpkg -i %s" % self.filename)
-        else:
-            installProgress.startUpdate()
-            res = installProgress.run(self.filename)
-            installProgress.finishUpdate()
-        return res
-
-class DscSrcPackage(DebPackage):
-    def __init__(self, filename=None, cache=None):
-        DebPackage.__init__(self, filename, cache)
-        self.depends = []
-        self.conflicts = []
-        self.binaries = []
-        if filename != None:
-            self.open(filename)
-    def getConflicts(self):
-        return self.conflicts
-    def getDepends(self):
-        return self.depends
-    def open(self, file):
-        depends_tags = ["Build-Depends:", "Build-Depends-Indep:"]
-        conflicts_tags = ["Build-Conflicts:", "Build-Conflicts-Indep:"]
-        for line in open(file):
-            # check b-d and b-c
-            for tag in depends_tags:
-                if line.startswith(tag):
-                    key = line[len(tag):].strip()
-                    self.depends.extend(apt_pkg.ParseSrcDepends(key))
-            for tag in conflicts_tags:
-                if line.startswith(tag):
-                    key = line[len(tag):].strip()
-                    self.conflicts.extend(apt_pkg.ParseSrcDepends(key))
-            # check binary and source and version
-            if line.startswith("Source:"):
-                self.pkgName = line[len("Source:"):].strip()
-            if line.startswith("Binary:"):
-                self.binaries = [pkg.strip() for pkg in line[len("Binary:"):].split(",")]
-            if line.startswith("Version:"):
-                self._sections["Version"] = line[len("Version:"):].strip()
-            # we are at the end 
-            if line.startswith("-----BEGIN PGP SIGNATURE-"):
-                break
-        s = "Install Build-Dependencies for source package '%s' that builds %s\n" % (self.pkgName, " ".join(self.binaries))
-        self._sections["Description"] = s
-        
-    def checkDeb(self):
-        if not self.checkConflicts():
-            for pkgname in self._installedConflicts:
-                if self._cache[pkgname]._pkg.Essential:
-                    raise Exception, "A essential package would be removed"
-                self._cache[pkgname].markDelete()
-        # FIXME: a additional run of the checkConflicts()
-        #        after _satisfyDepends() should probably be done
-        return self._satisfyDepends(self.depends)
-
-if __name__ == "__main__":
-    from cache import Cache
-    from progress import DpkgInstallProgress
-
-    cache = Cache()
-
-    vp = "www-browser"
-    print "%s virtual: %s" % (vp,cache.isVirtualPackage(vp))
-    providers = cache.getProvidingPackages(vp)
-    print "Providers for %s :" % vp
-    for pkg in providers:
-        print " %s" % pkg.name
-    
-    d = DebPackage(sys.argv[1], cache)
-    print "Deb: %s" % d.pkgname
-    if not d.checkDeb():
-        print "can't be satified"
-        print d._failureString
-    print "missing deps: %s" % d.missingDeps
-    print d.requiredChanges
-
-    print "Installing ..."
-    ret = d.install(DpkgInstallProgress())
-    print ret
-
-    #s = DscSrcPackage(cache, "../tests/3ddesktop_0.2.9-6.dsc")
-    #s.checkDep()
-    #print "Missing deps: ",s.missingDeps
-    #print "Print required changes: ", s.requiredChanges
-
-    s = DscSrcPackage(cache=cache)
-    d = "libc6 (>= 2.3.2), libaio (>= 0.3.96) | libaio1 (>= 0.3.96)"
-    print s._satisfyDepends(apt_pkg.ParseDepends(d))


More information about the PackageKit-commit mailing list