summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--.gitignore4
-rw-r--r--doc/NEWS (renamed from doc/Changelog)6
-rw-r--r--doc/TODO40
-rw-r--r--doc/TRANSLATING17
-rw-r--r--epydoc.conf1
-rw-r--r--etc/portato.cfg3
-rwxr-xr-xextensions.sh10
-rw-r--r--i18n/messages.pot136
-rw-r--r--plugins/etc_proposals.py4
-rw-r--r--plugins/new_version.py60
-rw-r--r--plugins/notify.py5
-rw-r--r--plugins/package_details.py6
-rw-r--r--portato/__init__.py56
-rw-r--r--portato/backend/__init__.py59
-rw-r--r--portato/backend/package.py10
-rw-r--r--portato/backend/portage/package.py14
-rw-r--r--portato/backend/portage/system.py21
-rw-r--r--portato/backend/system_interface.py22
-rw-r--r--portato/constants.py7
-rw-r--r--portato/db/__init__.py43
-rw-r--r--portato/db/eix_sql.py69
-rw-r--r--portato/db/hash.py (renamed from portato/db/dict.py)4
-rw-r--r--portato/db/sql.py19
-rw-r--r--portato/eix/__init__.py88
-rw-r--r--portato/eix/eix-format.html855
-rw-r--r--portato/eix/exceptions.py45
-rw-r--r--portato/eix/parser.pyx316
-rw-r--r--portato/eix/py_parser.py416
-rw-r--r--portato/gui/exception_handling.py7
-rw-r--r--portato/gui/queue.py2
-rw-r--r--portato/gui/templates/AboutWindow.ui48
-rw-r--r--portato/gui/templates/MailInfoWindow.ui46
-rw-r--r--portato/gui/templates/MainWindow.menu215
-rw-r--r--portato/gui/templates/MainWindow.ui429
-rw-r--r--portato/gui/templates/PkgListWindow.ui (renamed from portato/gui/templates/UpdateWindow.ui)59
-rw-r--r--portato/gui/templates/PluginWindow.ui72
-rw-r--r--portato/gui/templates/PreferenceWindow.ui17
-rw-r--r--portato/gui/templates/SearchWindow.ui36
-rw-r--r--portato/gui/templates/SplashScreen.ui11
-rw-r--r--portato/gui/utils.py7
-rw-r--r--portato/gui/windows/about.py8
-rw-r--r--portato/gui/windows/basic.py26
-rw-r--r--portato/gui/windows/main.py52
-rw-r--r--portato/gui/windows/pkglist.py (renamed from portato/gui/windows/update.py)69
-rw-r--r--portato/ipc.pxd52
-rw-r--r--portato/ipc.pyx173
-rw-r--r--portato/listener.py64
-rw-r--r--portato/plugin.py35
-rw-r--r--portato/waiting_queue.py7
-rw-r--r--setup.py31
-rw-r--r--test.py29
52 files changed, 3153 insertions, 679 deletions
diff --git a/.bzrignore b/.bzrignore
deleted file mode 100644
index 6e92f57..0000000
--- a/.bzrignore
+++ /dev/null
@@ -1 +0,0 @@
-tags
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..10d85cd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+tags
+*.pyc
+*.so
+*.c
diff --git a/doc/Changelog b/doc/NEWS
index fe8799b..a5d3186 100644
--- a/doc/Changelog
+++ b/doc/NEWS
@@ -1,3 +1,9 @@
+next:
+
+- allow eix as backend DB
+- use an internal messagequeue module instead of external shm
+- show the list of world packages
+
0.13.1:
- fix segfault in GLib
- correct config path handling for portage-2.1.7.x
diff --git a/doc/TODO b/doc/TODO
deleted file mode 100644
index 81c8d5c..0000000
--- a/doc/TODO
+++ /dev/null
@@ -1,40 +0,0 @@
-Documentation:
-==============
-
-Unittest:
-========
-
-- ALL!
-
-Backend:
-========
-
-- add Paludis support \
-- add pkgcore support |-> not necessairy if catapult is used
-- add equo support /
-
-- rewrite flags handling
-
-- also check installed packages if they block the current one
-
-- make sure, a package being removed from the queue is not needed as a dependency by another package
-- binary package support
-
-GUI:
-====
-
-Main Point: user preferences:
- - colors and font sizes
-
-- rotating systray icon
-- if a package has been merged, but there are still dependencies to be merged - move the dependencies up the tree (Updater)
-- move GUI prefs out of the system config
-- show reverse dependencies
-- reload package table when emerge is finished
-- show which package has a dependency that causes a block
-
-[quote]
-I would like to be able to see at a glance:
-1. How many packages I have installed. (Hopefully in the menubar)
-a. How many of the packages are installed, and the number there are in each category. (Just like you do with the queue: "x of y"::"installed of available")
-[/quote]
diff --git a/doc/TRANSLATING b/doc/TRANSLATING
index 4b49fa5..75d1c45 100644
--- a/doc/TRANSLATING
+++ b/doc/TRANSLATING
@@ -12,15 +12,28 @@ KBabel (kde-base/kbabel) or Gtranslator (app-text/gtranslator).
Getting the sources:
===================
+You do need the sources to make translations, as the installed program is not sufficient.
+Therefore you need to have dev-util/git installed.
-You do need the sources to make translations. The installed program is not sufficient.
Change into a local directory where you want to have the sources installed.
Then do:
-> bzr pull lp:portato
+> git clone git://github.com/Necoro/portato.git
You now should have the actual sources in the "portato" subdirectory.
+If you later on want to update these sources, you do:
+
+> git pull
+
+Important: If you are working on a given version, you need to change to the correct branch:
+
+> git checkout -b 0.13 origin/0.13
+
+where '0.13' has to be replaced by the version you are going to use.
+
+Have a look at http://www.git-scm.com for more information on how to use git.
+
To update an incomplete translation:
===================================
diff --git a/epydoc.conf b/epydoc.conf
index 62b6c73..0e81aee 100644
--- a/epydoc.conf
+++ b/epydoc.conf
@@ -27,7 +27,6 @@ sourcecode: yes
include-log: no
frames: yes
css: white
-redundant-details: yes
#
# Project
diff --git a/etc/portato.cfg b/etc/portato.cfg
index 2429dc7..10f5445 100644
--- a/etc/portato.cfg
+++ b/etc/portato.cfg
@@ -124,6 +124,7 @@ prefhint = f3f785
; allowed values:
; - sql : SQLite Database
; - dict : Hashmap in Memory
-type = sql
+; - eixsql: Eix + SQLite Database
+type = eixsql
# vim:ts=4:sw=4:noexpandtab:ft=cfg
diff --git a/extensions.sh b/extensions.sh
new file mode 100755
index 0000000..eb44d92
--- /dev/null
+++ b/extensions.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+cflags=$(python -c "from portato.backend import system; print system.get_global_settings('CFLAGS')")
+
+find -name "*.so" -print0 | xargs -0 rm -f
+find -name "*.c" -print0 | xargs -0 rm -f
+
+CFLAGS=$cflags python setup.py build_ext -i
+
+rm -rf build
diff --git a/i18n/messages.pot b/i18n/messages.pot
index aed996a..f148ce2 100644
--- a/i18n/messages.pot
+++ b/i18n/messages.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-08-31 22:04+0200\n"
+"POT-Creation-Date: 2009-08-31 22:12+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -573,7 +573,7 @@ msgstr ""
msgid "No %(old)s language file installed. Disable highlighting."
msgstr ""
-#: portato/gui/views.py:130 plugins/package_details.py:102
+#: portato/gui/views.py:130 plugins/package_details.py:108
#, python-format
msgid "Error: %s"
msgstr ""
@@ -836,6 +836,20 @@ msgstr ""
msgid "Update"
msgstr ""
+#: portato/eix/exceptions.py:26
+msgid "Unknown error."
+msgstr ""
+
+#: portato/eix/exceptions.py:37
+#, python-format
+msgid "End of file reached though it was not expected: '%s'"
+msgstr ""
+
+#: portato/eix/exceptions.py:45
+#, python-format
+msgid "Version '%s' is not supported."
+msgstr ""
+
#: portato/backend/flags.py:527
#, python-format
msgid "Conflicting values for masking status: %s"
@@ -867,11 +881,11 @@ msgstr ""
msgid "BUG in flags.new_masking_status. It returns '%s'"
msgstr ""
-#: portato/__init__.py:53
+#: portato/__init__.py:50
msgid "do not fork off as root"
msgstr ""
-#: portato/__init__.py:76
+#: portato/__init__.py:79
msgid "Starting Portato"
msgstr ""
@@ -906,31 +920,49 @@ msgid ""
"regenerated on each startup."
msgstr ""
-#: portato/db/__init__.py:40
-msgid "Cannot load SQLDatabase."
+#: portato/db/__init__.py:26
+msgid "eix + SQLite"
+msgstr ""
+
+#: portato/db/__init__.py:26
+msgid ""
+"Similar to SQLite, but now uses the eix database to get the package "
+"information.\n"
+"This should be much faster on startup, but requires that your eix database "
+"is always up-to-date."
msgstr ""
-#: portato/db/__init__.py:51
+#: portato/db/__init__.py:41 portato/db/__init__.py:56
#, python-format
-msgid "Unknown database type: %s"
+msgid "Cannot load %s."
msgstr ""
-#: portato/db/database.py:38
-msgid "ALL"
+#: portato/db/__init__.py:62
+#, python-format
+msgid "Unknown database type: %s"
msgstr ""
-#: portato/db/dict.py:94
+#: portato/db/hash.py:94
#, python-format
msgid ""
"Catched KeyError => %s seems not to be an available category. Have you "
"played with rsync-excludes?"
msgstr ""
-#: portato/db/dict.py:149
+#: portato/db/hash.py:149
#, python-format
msgid "Error while compiling search expression: '%s'."
msgstr ""
+#: portato/db/eix_sql.py:35
+#, python-format
+msgid "Cache file '%s' does not exist. Using default instead."
+msgstr ""
+
+#: portato/db/database.py:38
+msgid "ALL"
+msgstr ""
+
#: portato/db/sql.py:79
msgid "Cleaning database..."
msgstr ""
@@ -964,133 +996,153 @@ msgstr ""
msgid "Unrecognized line in configuration: %s"
msgstr ""
-#: portato/listener.py:94
+#: portato/listener.py:85
msgid "Listener has not been started."
msgstr ""
-#: portato/plugin.py:438 portato/plugin.py:441
+#: portato/listener.py:94
+#, python-format
+msgid "An exception occured while accessing the message queue: %s"
+msgstr ""
+
+#: portato/plugin.py:446 portato/plugin.py:449
+#, python-format
+msgid "Loading plugin module '%(plugin)s' failed: %(error)s"
+msgstr ""
+
+#: portato/plugin.py:459
#, python-format
-msgid "Loading plugin '%(plugin)s' failed: %(error)s"
+msgid "Loading widgets plugin '%(plugin)s' failed: %(error)s"
msgstr ""
-#: portato/plugin.py:451
+#: portato/plugin.py:462
+#, python-format
+msgid "Loading widgets of plugin '%(plugin)s' failed: %(error)s"
+msgstr ""
+
+#: portato/plugin.py:466
#, python-format
msgid "Widgets of plugin '%s' loaded."
msgstr ""
-#: portato/plugin.py:482
+#: portato/plugin.py:497
msgid "Plugin is disabled!"
msgstr ""
-#: portato/plugin.py:484
+#: portato/plugin.py:499
msgid "Plugin has unresolved dependencies - disabled!"
msgstr ""
-#: portato/plugin.py:488
+#: portato/plugin.py:503
#, python-format
msgid "Plugin '%s' loaded."
msgstr ""
-#: portato/plugin.py:528
+#: portato/plugin.py:543
#, python-format
msgid "Overriding hook '%(hook)s' with plugin '%(plugin)s'."
msgstr ""
-#: portato/plugin.py:586
+#: portato/plugin.py:601
#, python-format
msgid ""
"For hook '%(hook)s' an override is already defined by plugin '%(plugin)s'!"
msgstr ""
-#: portato/plugin.py:587
+#: portato/plugin.py:602
#, python-format
msgid "It is now replaced by the one from plugin '%s'!"
msgstr ""
-#: portato/plugin.py:620
+#: portato/plugin.py:635
#, python-format
msgid ""
"Dependant '%(dep)s' for '%(hook)s' in plugin '%(plugin)s' not found! Adding "
"nevertheless."
msgstr ""
-#: plugins/etc_proposals.py:34
+#: portato/plugin.py:704 portato/plugin.py:707
+#, python-format
+msgid "Registrating plugin '%(plugin)s' failed: %(error)s"
+msgstr ""
+
+#: plugins/etc_proposals.py:32
msgid "Cannot start etc-proposals. Not root!"
msgstr ""
-#: plugins/package_details.py:67
+#: plugins/package_details.py:73
msgid "Shows the Changelog of a package"
msgstr ""
-#: plugins/package_details.py:69
+#: plugins/package_details.py:75
msgid "Changelog"
msgstr ""
-#: plugins/package_details.py:79
+#: plugins/package_details.py:85
msgid "Shows the ebuild of a package"
msgstr ""
-#: plugins/package_details.py:82
+#: plugins/package_details.py:88
msgid "Ebuild"
msgstr ""
-#: plugins/package_details.py:89
+#: plugins/package_details.py:95
msgid "Shows the installed files of a package"
msgstr ""
-#: plugins/package_details.py:91
+#: plugins/package_details.py:97
msgid "Files"
msgstr ""
-#: plugins/package_details.py:105
+#: plugins/package_details.py:111
msgid "Shows the dependencies of a package"
msgstr ""
-#: plugins/package_details.py:107
+#: plugins/package_details.py:113
msgid "Dependencies"
msgstr ""
-#: plugins/package_details.py:179
+#: plugins/package_details.py:185
#, python-format
msgid "If '%s' is disabled"
msgstr ""
-#: plugins/package_details.py:181
+#: plugins/package_details.py:187
#, python-format
msgid "If '%s' is enabled"
msgstr ""
-#: plugins/package_details.py:187
+#: plugins/package_details.py:193
msgid "One of the following"
msgstr ""
-#: plugins/package_details.py:192
+#: plugins/package_details.py:198
msgid "All of the following"
msgstr ""
-#: plugins/package_details.py:203
+#: plugins/package_details.py:209
msgid ""
"Can't display dependencies: This package has an unsupported dependency "
"string."
msgstr ""
-#: plugins/notify.py:24
+#: plugins/notify.py:23
msgid "Cannot import 'pynotify'."
msgstr ""
-#: plugins/notify.py:36
+#: plugins/notify.py:35
msgid "Notify called while process is still running!"
msgstr ""
-#: plugins/notify.py:40
+#: plugins/notify.py:39
msgid "Emerge finished!"
msgstr ""
-#: plugins/notify.py:44
+#: plugins/notify.py:43
msgid "Emerge failed!"
msgstr ""
-#: plugins/notify.py:45
+#: plugins/notify.py:44
#, python-format
msgid "Error Code: %d"
msgstr ""
diff --git a/plugins/etc_proposals.py b/plugins/etc_proposals.py
index 83b38f7..052f3d3 100644
--- a/plugins/etc_proposals.py
+++ b/plugins/etc_proposals.py
@@ -10,8 +10,6 @@
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>
-from portato.helper import error
-
import os
from subprocess import Popen
@@ -31,7 +29,7 @@ class EtcProposals (WidgetPlugin):
if os.getuid() == 0:
Popen(self.prog+options)
else:
- error("ETC_PROPOSALS :: %s",_("Cannot start etc-proposals. Not root!"))
+ helper.error("ETC_PROPOSALS :: %s",_("Cannot start etc-proposals. Not root!"))
def hook (self, *args, **kwargs):
"""Entry point for this plugin."""
diff --git a/plugins/new_version.py b/plugins/new_version.py
index 94e61ca..9fa5f4e 100644
--- a/plugins/new_version.py
+++ b/plugins/new_version.py
@@ -12,16 +12,11 @@
from portato.helper import debug, warning
-try:
- from bzrlib import plugin, branch
-except ImportError:
- plugin = branch = None
- warning("NEW_VERSION :: Cannot import 'bzrlib'")
-
+from subprocess import Popen, PIPE
import gobject
from portato import get_listener
-from portato.constants import REPOURI, VERSION, APP_ICON, APP
+from portato.constants import REPOURI, REVISION, APP_ICON, APP
from portato.gui.utils import GtkThread
class NewVersionFinder(WidgetPlugin):
@@ -29,7 +24,7 @@ class NewVersionFinder(WidgetPlugin):
Checks for a new version of portato every 30 minutes and on startup.
"""
__author__ = "René 'Necoro' Neumann"
- __dependency__ = ["dev-util/bzr"]
+ __dependency__ = ["dev-util/git"]
def init (self):
self.add_call("main", self.run)
@@ -37,20 +32,30 @@ class NewVersionFinder(WidgetPlugin):
def widget_init (self):
self.create_widget("Plugin Menu", "Check for new _versions", activate = self.menu)
+ def get_notify_callback (self, rev):
+ def callback():
+ get_listener().send_notify(
+ base = "New Portato Live Version Found",
+ descr = "The most recent revision is %s." % rev,
+ icon = APP_ICON)
+ return False
+
+ return callback
+
def find_version (self, rev):
- try:
- b = branch.Branch.open(REPOURI)
- except Exception, e:
- warning("NEW_VERSION :: Exception occured while accessing the remote branch: %s", str(e))
- return
-
- debug("NEW_VERSION :: Installed rev: %s - Current rev: %s", rev, b.revno())
- if int(rev) < int(b.revno()):
- def callback():
- get_listener().send_notify(base = "New Portato Live Version Found", descr = "You have rev. %s, but the most recent revision is %s." % (rev, b.revno()), icon = APP_ICON)
- return False
-
- gobject.idle_add(callback)
+
+ repo, branch = REPOURI.split('::')
+
+ remote_rev = Popen(['git', 'ls-remote', repo, branch], stdout = PIPE).communicate()[0].strip().split('\t')
+
+ if len(remote_rev) and remote_rev[1] not in (branch, 'refs/heads/'+branch, 'refs/tags/'+branch):
+ warning('NEW_VERSION :: Returned revision information looks strange: %s', str(remote_rev))
+ else:
+ remote_rev = remote_rev[0]
+ debug("NEW_VERSION :: Installed rev: %s - Current rev: %s", remote_rev, rev)
+
+ if rev != remote_rev:
+ gobject.idle_add(self.get_notify_callback(remote_rev))
def start_thread(self, rev):
t = GtkThread(target = self.find_version, name = "Version Updater Thread", args = (rev,))
@@ -62,16 +67,11 @@ class NewVersionFinder(WidgetPlugin):
"""
Run the thread once.
"""
- v = VERSION.split()
- if len(v) != 3:
+ if not REVISION:
return None
-
- rev = v[-1]
-
- plugin.load_plugins() # to have lp: addresses parsed
- self.start_thread(rev)
- return rev
+ self.start_thread(REVISION)
+ return REVISION
def run (self, *args, **kwargs):
"""
@@ -82,4 +82,4 @@ class NewVersionFinder(WidgetPlugin):
if rev is not None:
gobject.timeout_add(30*60*1000, self.start_thread, rev) # call it every 30 minutes
-register(NewVersionFinder, (branch is None))
+register(NewVersionFinder, REVISION == '')
diff --git a/plugins/notify.py b/plugins/notify.py
index 3670e20..4aba2c6 100644
--- a/plugins/notify.py
+++ b/plugins/notify.py
@@ -14,14 +14,13 @@ disable = False
from portato import get_listener
-from portato.helper import warning, error, debug
from portato.constants import APP_ICON, APP
try:
import pynotify
except ImportError:
disable = True
- warning("NOTIFY :: %s", _("Cannot import 'pynotify'."))
+ helper.warning("NOTIFY :: %s", _("Cannot import 'pynotify'."))
class Notify (Plugin):
__author__ = "René 'Necoro' Neumann"
@@ -33,7 +32,7 @@ class Notify (Plugin):
def notify (self, retcode, **kwargs):
if retcode is None:
- warning("NOTIFY :: %s", _("Notify called while process is still running!"))
+ helper.warning("NOTIFY :: %s", _("Notify called while process is still running!"))
else:
icon = APP_ICON
if retcode == 0:
diff --git a/plugins/package_details.py b/plugins/package_details.py
index 6a17f1e..19f3126 100644
--- a/plugins/package_details.py
+++ b/plugins/package_details.py
@@ -23,13 +23,19 @@ class Detail (WidgetPlugin):
"""
__author__ = "René 'Necoro' Neumann"
+
_view_ = None
_old_pkg = None
+ _widget_ = None
+ _widget_name_ = None
def init(self):
self.add_call("update_table", self._update, type = "after")
def widget_init (self):
+ if (self._widget_ is None) or (self._widget_name_ is None):
+ raise PluginLoadException, ("Has not set _widget_ or _widget_name_.")
+
self.add_widget("Package Notebook", (self._widget_, self._widget_name_))
# if the detail was updated before it was actually initialized, update it again :)
diff --git a/portato/__init__.py b/portato/__init__.py
index 653329c..98c019d 100644
--- a/portato/__init__.py
+++ b/portato/__init__.py
@@ -14,15 +14,16 @@ from __future__ import absolute_import
import gettext, locale
import sys, os
-import subprocess, threading
-import atexit
from optparse import OptionParser, SUPPRESS_HELP
-from . import log
-from .constants import LOCALE_DIR, APP, VERSION
-from .su import detect_su_command
+from .log import start as logstart
+from .constants import LOCALE_DIR, APP, VERSION, REVISION
from .helper import debug, info, error
+# set better version info
+if REVISION:
+ VERSION = '%s (git: %s)' % (VERSION, REVISION)
+
# listener-handling
__listener = None
@@ -46,7 +47,7 @@ def get_parser (use_ = False):
parser = OptionParser(version = vers, prog = "portato", description = desc, usage = usage)
- parser.add_option("--shm", action = "store", nargs = 3, type="long", dest = "shm",
+ parser.add_option("--mq", action = "store", nargs = 1, type="long", dest = "mq", default = None,
help = SUPPRESS_HELP)
parser.add_option("-F", "--no-fork", action = "store_true", dest = "nofork", default = False,
@@ -54,31 +55,34 @@ def get_parser (use_ = False):
return parser
-def start():
-
+def _sub_start ():
# set gettext stuff
locale.setlocale(locale.LC_ALL, '')
gettext.install(APP, LOCALE_DIR, unicode = True)
+def start():
+
+ # set gettext stuff
+ _sub_start()
+
# start logging
- log.start(file=False)
+ logstart(file=False)
# run parser
(options, args) = get_parser().parse_args()
- # close listener at exit
- atexit.register(get_listener().close)
-
if options.nofork or os.getuid() == 0: # start GUI
- log.start(file = True) # start logging to file
+
+ # close listener at exit
+ import atexit
+ atexit.register(get_listener().close)
+
+ logstart(file = True) # start logging to file
from .gui import run
info("%s v. %s", _("Starting Portato"), VERSION)
- if options.shm:
- get_listener().set_send(*options.shm)
- else:
- get_listener().set_send()
+ get_listener().set_send(options.mq)
try:
run()
@@ -87,14 +91,14 @@ def start():
else: # start us again in root modus and launch listener
- import shm_wra