From c680afd2a2a913c7d43e5db515d4d4ab7762d010 Mon Sep 17 00:00:00 2001 From: abki Date: Wed, 1 Jul 2009 14:09:09 +0200 Subject: [PATCH 1/6] initial commit --- __init__.py | 0 commands/__init__.py | 0 commands/clean.sh | 5 + commands/layman | 37 + commands/lib/__init__.py | 0 commands/lib/layman/__init__.py | 1 + commands/lib/layman/action.py | 523 +++++ commands/lib/layman/bin/__init__.py | 0 commands/lib/layman/config.py | 325 ++++ commands/lib/layman/db.py | 588 ++++++ commands/lib/layman/debug.py | 507 +++++ commands/lib/layman/overlay.py | 244 +++ commands/lib/layman/overlays/__init__.py | 1 + commands/lib/layman/overlays/bzr.py | 66 + commands/lib/layman/overlays/cvs.py | 83 + commands/lib/layman/overlays/darcs.py | 64 + commands/lib/layman/overlays/git.py | 77 + commands/lib/layman/overlays/mercurial.py | 64 + commands/lib/layman/overlays/overlay.py | 301 +++ commands/lib/layman/overlays/rsync.py | 73 + commands/lib/layman/overlays/svn.py | 75 + commands/lib/layman/overlays/tar.py | 189 ++ commands/lib/layman/utils.py | 208 ++ commands/lib/layman/version.py | 24 + commands/manage_layman.py | 72 + commands/mylayman.cfg | 58 + commands/overlays.txt | 1232 ++++++++++++ commands/overlays.xml | 2999 +++++++++++++++++++++++++++++ commands/parse.py | 150 ++ commands/whoosh_manager.py | 56 + models.py | 29 + planet.py | 99 + templates/ebuildfind/bakup.html | 0 templates/ebuildfind/base.html | 131 ++ templates/ebuildfind/index.html | 2 + templates/ebuildfind/search.html | 21 + urls.py | 15 + views.py | 48 + 38 files changed, 8367 insertions(+) create mode 100644 __init__.py create mode 100644 commands/__init__.py create mode 100644 commands/clean.sh create mode 100755 commands/layman create mode 100644 commands/lib/__init__.py create mode 100644 commands/lib/layman/__init__.py create mode 100644 commands/lib/layman/action.py create mode 100644 commands/lib/layman/bin/__init__.py create mode 100644 commands/lib/layman/config.py create mode 100644 commands/lib/layman/db.py create mode 100644 commands/lib/layman/debug.py create mode 100644 commands/lib/layman/overlay.py create mode 100644 commands/lib/layman/overlays/__init__.py create mode 100644 commands/lib/layman/overlays/bzr.py create mode 100644 commands/lib/layman/overlays/cvs.py create mode 100644 commands/lib/layman/overlays/darcs.py create mode 100644 commands/lib/layman/overlays/git.py create mode 100644 commands/lib/layman/overlays/mercurial.py create mode 100644 commands/lib/layman/overlays/overlay.py create mode 100644 commands/lib/layman/overlays/rsync.py create mode 100644 commands/lib/layman/overlays/svn.py create mode 100644 commands/lib/layman/overlays/tar.py create mode 100644 commands/lib/layman/utils.py create mode 100644 commands/lib/layman/version.py create mode 100644 commands/manage_layman.py create mode 100644 commands/mylayman.cfg create mode 100644 commands/overlays.txt create mode 100644 commands/overlays.xml create mode 100644 commands/parse.py create mode 100644 commands/whoosh_manager.py create mode 100644 models.py create mode 100644 planet.py create mode 100644 templates/ebuildfind/bakup.html create mode 100644 templates/ebuildfind/base.html create mode 100755 templates/ebuildfind/index.html create mode 100644 templates/ebuildfind/search.html create mode 100644 urls.py create mode 100644 views.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/commands/__init__.py b/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/commands/clean.sh b/commands/clean.sh new file mode 100644 index 0000000..44a9815 --- /dev/null +++ b/commands/clean.sh @@ -0,0 +1,5 @@ +#!/usr/bin/bash + +rm -rf var/layman/$1 +./layman -c mylayman.cfg -a $1 +python parse.py \ No newline at end of file diff --git a/commands/layman b/commands/layman new file mode 100755 index 0000000..b0aa4f5 --- /dev/null +++ b/commands/layman @@ -0,0 +1,37 @@ +#!/usr/bin/python +################################################################################ +# LAYMAN - A UTILITY TO SELECT AND UPDATE GENTOO OVERLAYS +################################################################################ +# Distributed under the terms of the GNU General Public License v2 +# +# Copyright: +# (c) 2005 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# + +__version__ = "$Id$" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.config import Config +from layman.action import Actions + +#=============================================================================== +# +# MAIN +# +#------------------------------------------------------------------------------- + +def main(): + + Actions(Config()) + +if __name__ == "__main__": + main() diff --git a/commands/lib/__init__.py b/commands/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/commands/lib/layman/__init__.py b/commands/lib/layman/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/commands/lib/layman/__init__.py @@ -0,0 +1 @@ +# diff --git a/commands/lib/layman/action.py b/commands/lib/layman/action.py new file mode 100644 index 0000000..b7b36b6 --- /dev/null +++ b/commands/lib/layman/action.py @@ -0,0 +1,523 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN ACTIONS +################################################################################# +# File: action.py +# +# Handles layman actions. +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +''' Provides the different actions that can be performed by layman.''' + +__version__ = "$Id: action.py 312 2007-04-09 19:45:49Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +import os, sys + +from layman.db import DB, RemoteDB + +from layman.debug import OUT + +#=============================================================================== +# +# Class Fetch +# +#------------------------------------------------------------------------------- + +class Fetch: + ''' Fetches the overlay listing. + + >>> import os + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> cache = os.tmpnam() + >>> config = {'overlays' : + ... 'file://' + here + '/tests/testfiles/global-overlays.xml', + ... 'cache' : cache, + ... 'nocheck' : True, + ... 'proxy' : None, + ... 'quietness':3} + >>> a = Fetch(config) + >>> a.run() + 0 + >>> b = open(a.db.path(config['overlays'])) + >>> b.readlines()[24] + ' A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org].\\n' + + >>> b.close() + >>> os.unlink(a.db.path(config['overlays'])) + + >>> a.db.overlays.keys() + [u'wrobel', u'wrobel-stable'] + ''' + + def __init__(self, config): + self.db = RemoteDB(config) + + def run(self): + '''Fetch the overlay listing.''' + try: + self.db.cache() + except Exception, error: + OUT.die('Failed to fetch overlay list!\nError was: ' + + str(error)) + + return 0 + +#=============================================================================== +# +# Class Sync +# +#------------------------------------------------------------------------------- + +class Sync: + ''' Syncs the selected overlays.''' + + def __init__(self, config): + + self.db = DB(config) + + self.rdb = RemoteDB(config) + + self.quiet = int(config['quietness']) < 3 + + self.selection = config['sync'] + + if config['sync_all'] or 'ALL' in self.selection: + self.selection = self.db.overlays.keys() + + enc = sys.getfilesystemencoding() + if enc: + self.selection = [i.decode(enc) for i in self.selection] + + def run(self): + '''Synchronize the overlays.''' + + OUT.debug('Updating selected overlays', 6) + + warnings = [] + success = [] + for i in self.selection: + ordb = self.rdb.select(i) + odb = self.db.select(i) + if ordb and odb and ordb.src != odb.src: + warnings.append( + 'The source of the overlay "' + i + '" seems to have c' + 'hanged. You currently sync from "' + odb.src + '" whi' + 'le the global layman list reports "' + ordb.src + '" ' + 'as correct location. Please consider removing and rea' + 'dding the overlay!') + + try: + self.db.sync(i, self.quiet) + success.append('Successfully synchronized overlay "' + i + '".') + except Exception, error: + warnings.append( + 'Failed to sync overlay "' + i + '".\nError was: ' + + str(error)) + + if success: + OUT.info('\nSuccess:\n------\n', 3) + for i in success: + OUT.info(i, 3) + + if warnings: + OUT.warn('\nErrors:\n------\n', 2) + for i in warnings: + OUT.warn(i + '\n', 2) + return 1 + + return 0 + +#=============================================================================== +# +# Class Add +# +#------------------------------------------------------------------------------- + +class Add: + ''' Adds the selected overlays.''' + + def __init__(self, config): + + self.config = config + + self.db = DB(config) + + self.rdb = RemoteDB(config) + + self.quiet = int(config['quietness']) < 3 + + self.selection = config['add'] + + enc = sys.getfilesystemencoding() + if enc: + self.selection = [i.decode(enc) for i in self.selection] + + if 'ALL' in self.selection: + self.selection = self.rdb.overlays.keys() + + def run(self): + '''Add the overlay.''' + + OUT.debug('Adding selected overlays', 6) + + result = 0 + + for i in self.selection: + overlay = self.rdb.select(i) + + OUT.debug('Selected overlay', 7) + + if overlay: + try: + self.db.add(overlay, self.quiet) + OUT.info('Successfully added overlay "' + i + '".', 2) + except Exception, error: + OUT.warn('Failed to add overlay "' + i + '".\nError was: ' + + str(error), 2) + result = 1 + else: + OUT.warn('Overlay "' + i + '" does not exist!', 2) + result = 1 + + return result + +#=============================================================================== +# +# Class Delete +# +#------------------------------------------------------------------------------- + +class Delete: + ''' Deletes the selected overlays.''' + + def __init__(self, config): + + self.db = DB(config) + + self.selection = config['delete'] + + enc = sys.getfilesystemencoding() + if enc: + self.selection = [i.decode(enc) for i in self.selection] + + if 'ALL' in self.selection: + self.selection = self.db.overlays.keys() + + def run(self): + '''Delete the overlay.''' + + OUT.debug('Deleting selected overlays', 6) + + result = 0 + + for i in self.selection: + overlay = self.db.select(i) + + OUT.debug('Selected overlay', 7) + + if overlay: + try: + self.db.delete(overlay) + OUT.info('Successfully deleted overlay "' + i + '".', 2) + except Exception, error: + OUT.warn('Failed to delete overlay "' + i + '".\nError was: ' + + str(error), 2) + result = 1 + else: + OUT.warn('Overlay "' + i + '" does not exist!', 2) + result = 1 + + return result + +#=============================================================================== +# +# Class Info +# +#------------------------------------------------------------------------------- + +class Info: + ''' Print information about the specified overlays. + + >>> import os + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> cache = os.tmpnam() + >>> config = {'overlays' : + ... 'file://' + here + '/tests/testfiles/global-overlays.xml', + ... 'cache' : cache, + ... 'proxy' : None, + ... 'info' : ['wrobel'], + ... 'nocheck' : False, + ... 'verbose': False, + ... 'quietness':3} + >>> a = Info(config) + >>> a.rdb.cache() + >>> OUT.color_off() + >>> a.run() + * wrobel + * ~~~~~~ + * Source : https://overlays.gentoo.org/svn/dev/wrobel + * Contact : nobody@gentoo.org + * Type : Subversion; Priority: 10 + * + * Description: + * Test + * + 0 + ''' + + def __init__(self, config): + + OUT.debug('Creating RemoteDB handler', 6) + + self.rdb = RemoteDB(config) + self.config = config + + self.selection = config['info'] + + enc = sys.getfilesystemencoding() + if enc: + self.selection = [i.decode(enc) for i in self.selection] + + if 'ALL' in self.selection: + self.selection = self.rdb.overlays.keys() + + def run(self): + ''' Print information about the selected overlays.''' + + result = 0 + + for i in self.selection: + overlay = self.rdb.select(i) + + if overlay: + # Is the overlay supported? + OUT.info(overlay.__str__(), 1) + if not overlay.is_official(): + OUT.warn('*** This is no official gentoo overlay ***\n', 1) + if not overlay.is_supported(): + OUT.error('*** You are lacking the necessary tools to install t' + 'his overlay ***\n') + else: + OUT.warn('Overlay "' + i + '" does not exist!', 2) + result = 1 + + return result + +#=============================================================================== +# +# Class List +# +#------------------------------------------------------------------------------- + +class List: + ''' Lists the available overlays. + + >>> import os + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> cache = os.tmpnam() + >>> config = {'overlays' : + ... 'file://' + here + '/tests/testfiles/global-overlays.xml', + ... 'cache' : cache, + ... 'proxy' : None, + ... 'nocheck' : False, + ... 'verbose': False, + ... 'quietness':3, + ... 'width':80} + >>> a = List(config) + >>> a.rdb.cache() + >>> OUT.color_off() + >>> a.run() + * wrobel [Subversion] (https://o.g.o/svn/dev/wrobel ) + 0 + >>> a.config['verbose'] = True + >>> a.run() + * wrobel + * ~~~~~~ + * Source : https://overlays.gentoo.org/svn/dev/wrobel + * Contact : nobody@gentoo.org + * Type : Subversion; Priority: 10 + * + * Description: + * Test + * + * *** This is no official gentoo overlay *** + * + * wrobel-stable + * ~~~~~~~~~~~~~ + * Source : rsync://gunnarwrobel.de/wrobel-stable + * Contact : nobody@gentoo.org + * Type : Rsync; Priority: 50 + * + * Description: + * A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org]. + * + 0 + ''' + + def __init__(self, config): + + OUT.debug('Creating RemoteDB handler', 6) + + self.rdb = RemoteDB(config) + self.config = config + + def run(self): + ''' List the available overlays.''' + + for i in self.rdb.list(self.config['verbose'], self.config['width']): + # Is the overlay supported? + if i[1]: + # Is this an official overlay? + if i[2]: + OUT.info(i[0], 1) + # Unofficial overlays will only be listed if we are not + # checking or listing verbose + elif self.config['nocheck'] or self.config['verbose']: + # Give a reason why this is marked yellow if it is a verbose + # listing + if self.config['verbose']: + OUT.warn('*** This is no official gentoo overlay ***\n', 1) + OUT.warn(i[0], 1) + # Unsupported overlays will only be listed if we are not checking + # or listing verbose + elif self.config['nocheck'] or self.config['verbose']: + # Give a reason why this is marked red if it is a verbose + # listing + if self.config['verbose']: + OUT.error('*** You are lacking the necessary tools to insta' + 'll this overlay ***\n') + OUT.error(i[0]) + + return 0 + +#=============================================================================== +# +# Class ListLocal +# +#------------------------------------------------------------------------------- + +class ListLocal: + ''' Lists the local overlays.''' + + def __init__(self, config): + self.db = DB(config) + self.config = config + + def run(self): + '''List the overlays.''' + + for i in self.db.list(self.config['verbose']): + + OUT.debug('Printing local overlay.', 8) + + # Is the overlay supported? + if i[1]: + # Is this an official overlay? + if i[2]: + OUT.info(i[0], 1) + # Unofficial overlays will only be listed if we are not + # checking or listing verbose + else: + # Give a reason why this is marked yellow if it is a verbose + # listing + if self.config['verbose']: + OUT.warn('*** This is no official gentoo overlay ***\n', 1) + OUT.warn(i[0], 1) + # Unsupported overlays will only be listed if we are not checking + # or listing verbose + else: + # Give a reason why this is marked red if it is a verbose + # listing + if self.config['verbose']: + OUT.error('*** You are lacking the necessary tools to insta' + 'll this overlay ***\n') + OUT.error(i[0]) + + return 0 + +#=============================================================================== +# +# Class Actions +# +#------------------------------------------------------------------------------- + +class Actions: + '''Dispatches to the actions the user selected. ''' + + # Given in order of precedence + actions = [('fetch', Fetch), + ('add', Add), + ('sync', Sync), + ('info', Info), + ('sync_all', Sync), + ('delete', Delete), + ('list', List), + ('list_local', ListLocal),] + + def __init__(self, config): + + # Make fetching the overlay list a default action + if not 'nofetch' in config.keys(): + # Actions that implicitely call the fetch operation before + fetch_actions = ['fetch', 'sync', 'sync_all', 'list'] + for i in fetch_actions: + if i in config.keys(): + # Implicitely call fetch, break loop + Fetch(config).run() + break + + result = 0 + + # Set the umask + umask = config['umask'] + try: + new_umask = int(umask, 8) + old_umask = os.umask(new_umask) + except Exception, error: + OUT.die('Failed setting to umask "' + umask + '"!\nError was: ' + + str(error)) + + for i in self.actions: + + OUT.debug('Checking for action', 7) + + if i[0] in config.keys(): + result += i[1](config).run() + + # Reset umask + os.umask(old_umask) + + if not result: + sys.exit(0) + else: + sys.exit(1) + +#=============================================================================== +# +# Testing +# +#------------------------------------------------------------------------------- + +if __name__ == '__main__': + import doctest, sys + + # Ignore warnings here. We are just testing + from warnings import filterwarnings, resetwarnings + filterwarnings('ignore') + + doctest.testmod(sys.modules[__name__]) + + resetwarnings() diff --git a/commands/lib/layman/bin/__init__.py b/commands/lib/layman/bin/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/commands/lib/layman/config.py b/commands/lib/layman/config.py new file mode 100644 index 0000000..ba57c81 --- /dev/null +++ b/commands/lib/layman/config.py @@ -0,0 +1,325 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN CONFIGURATION +################################################################################# +# File: config.py +# +# Handles layman configuration +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +'''Defines the configuration options and provides parsing functionality.''' + +__version__ = "$Id: config.py 286 2007-01-09 17:48:23Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +import sys, ConfigParser + +from optparse import OptionParser, OptionGroup +from layman.debug import OUT +from layman.version import VERSION + +#=============================================================================== +# +# Class Config +# +#------------------------------------------------------------------------------- + +class Config(object): + '''Handles the configuration.''' + + def __init__(self): + ''' + Creates and describes all possible polymeraZe options and creates + a debugging object. + + >>> import os.path + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> sys.argv.append('--config') + >>> sys.argv.append(here + '/../etc/layman.cfg') + >>> a = Config() + >>> a['overlays'] + '\\nhttp://www.gentoo.org/proj/en/overlays/layman-global.txt' + >>> sorted(a.keys()) + ['cache', 'config', 'local_list', 'make_conf', 'nocheck', 'overlays', 'proxy', 'quietness', 'storage', 'umask', 'width'] + ''' + + self.defaults = {'config' : '/etc/layman/layman.cfg', + 'storage' : '/usr/portage/local/layman', + 'cache' : '%(storage)s/cache', + 'local_list': '%(storage)s/overlays.xml', + 'make_conf' : '%(storage)s/make.conf', + 'nocheck' : 'yes', + 'proxy' : '', + 'umask' : '0022', + 'overlays' : + 'http://www.gentoo.org/proj/en/overlays/layman-global.' + 'txt',} + + + self.parser = OptionParser( + usage = '\n\nlayman -a/-d/-S|overlay\nlayman -f [-o url]\nlayman' \ + ' -l|-L', + version = VERSION) + + #----------------------------------------------------------------- + # Main Options + + group = OptionGroup(self.parser, + '') + + group.add_option('-a', + '--add', + action = 'append', + help = 'Add the given overlay from the cached remote li' + 'st to your locally installed overlays.. Specify "ALL" ' + 'to add all overlays from the remote list.') + + group.add_option('-d', + '--delete', + action = 'append', + help = 'Remove the given overlay from your locally inst' + 'alled overlays. Specify "ALL" to remove all overlays') + + group.add_option('-s', + '--sync', + action = 'append', + help = 'Update the specified overlay. Use "ALL" as para' + 'meter to synchronize all overlays') + + group.add_option('-i', + '--info', + action = 'append', + help = 'Display information about the specified overlay' + '.') + + group.add_option('-S', + '--sync-all', + action = 'store_true', + help = 'Update all overlays.') + + group.add_option('-L', + '--list', + action = 'store_true', + help = 'List the contents of the remote list.') + + group.add_option('-l', + '--list-local', + action = 'store_true', + help = 'List the locally installed overlays.') + + group.add_option('-f', + '--fetch', + action = 'store_true', + help = 'Fetch a remote list of overlays. This option is' + ' deprecated. The fetch operation will be performed by ' + 'default when you run sync, sync-all, or list.') + + group.add_option('-n', + '--nofetch', + action = 'store_true', + help = 'Do not fetch a remote list of overlays.') + + group.add_option('-p', + '--priority', + action = 'store', + help = 'Use this with the --add switch to set the prior' + 'ity of the added overlay. This will influence the sort' + 'ing order of the overlays in the PORTDIR_OVERLAY varia' + 'ble.') + + self.parser.add_option_group(group) + + #----------------------------------------------------------------- + # Additional Options + + group = OptionGroup(self.parser, + '') + + group.add_option('-c', + '--config', + action = 'store', + help = 'Path to the config file [default: ' \ + + self.defaults['config'] + '].') + + group.add_option('-o', + '--overlays', + action = 'append', + help = 'The list of overlays [default: ' \ + + self.defaults['overlays'] + '].') + + self.parser.add_option_group(group) + + #----------------------------------------------------------------- + # Output Options + + group = OptionGroup(self.parser, + '') + + group.add_option('-v', + '--verbose', + action = 'store_true', + help = 'Increase the amount of output and describe the ' + 'overlays.') + + group.add_option('-q', + '--quiet', + action = 'store_true', + help = 'Yield no output. Please be careful with this op' + 'tion: If the processes spawned by layman when adding o' + 'r synchronizing overlays require any input layman will' + ' hang without telling you why. This might happen for e' + 'xample if your overlay resides in subversion and the S' + 'SL certificate of the server needs acceptance.') + + group.add_option('-N', + '--nocolor', + action = 'store_true', + help = 'Remove color codes from the layman output.') + + group.add_option('-Q', + '--quietness', + action = 'store', + type = 'int', + default = '4', + help = 'Set the level of output (0-4). Default: 4. Once' + ' you set this below 2 the same warning as given for --' + 'quiet applies! ') + + group.add_option('-W', + '--width', + action = 'store', + type = 'int', + default = '0', + help = 'Sets the screen width. This setting is usually ' + 'not required as layman is capable of detecting the ava' + 'available number of columns automatically.') + + group.add_option('-k', + '--nocheck', + action = 'store_true', + help = 'Do not check overlay definitions and do not i' + 'ssue a warning if description or contact information' + ' are missing.') + + self.parser.add_option_group(group) + + #----------------------------------------------------------------- + # Debug Options + + OUT.cli_opts(self.parser) + + # Parse the command line first since we need to get the config + # file option. + (self.options, args) = self.parser.parse_args() + + # handle debugging + OUT.cli_handle(self.options) + + if self.options.__dict__['nocolor']: + OUT.color_off() + + # Fetch only an alternate config setting from the options + if not self.options.__dict__['config'] is None: + self.defaults['config'] = self.options.__dict__['config'] + + OUT.debug('Got config file at ' + self.defaults['config'], 8) + + # Now parse the config file + self.config = ConfigParser.ConfigParser(self.defaults) + self.config.add_section('MAIN') + + # handle quietness + if self['quiet']: + OUT.set_info_level(1) + OUT.set_warn_level(1) + self.defaults['quietness'] = 0 + + elif 'quietness' in self.keys(): + OUT.set_info_level(int(self['quietness'])) + OUT.set_warn_level(int(self['quietness'])) + + OUT.debug('Reading config file at ' + self.defaults['config'], 8) + + self.config.read(self.defaults['config']) + + def __getitem__(self, key): + + if key == 'overlays': + overlays = '' + if (key in self.options.__dict__.keys() + and not self.options.__dict__[key] is None): + overlays = '\n'.join(self.options.__dict__[key]) + if self.config.has_option('MAIN', 'overlays'): + overlays += '\n' + self.config.get('MAIN', 'overlays') + if overlays: + return overlays + + OUT.debug('Retrieving option', 8) + + if (key in self.options.__dict__.keys() + and not self.options.__dict__[key] is None): + return self.options.__dict__[key] + + OUT.debug('Retrieving option', 8) + + if self.config.has_option('MAIN', key): + if key == 'nocheck': + if self.config.get('MAIN', key).lower() == 'yes': + return True + else: + return False + return self.config.get('MAIN', key) + + OUT.debug('Retrieving option', 8) + + if key in self.defaults.keys(): + return self.defaults[key] + + OUT.debug('Retrieving option', 8) + + return None + + def keys(self): + '''Special handler for the configuration keys.''' + + OUT.debug('Retrieving keys', 8) + + keys = [i for i in self.options.__dict__.keys() + if not self.options.__dict__[i] is None] + + OUT.debug('Retrieving keys', 8) + + keys += [name for name, value in self.config.items('MAIN') + if not name in keys] + + OUT.debug('Retrieving keys', 8) + + keys += [i for i in self.defaults.keys() + if not i in keys] + + OUT.debug('Retrieving keys', 8) + + return keys + + +#=============================================================================== +# +# Testing +# +#------------------------------------------------------------------------------- + +if __name__ == '__main__': + import doctest + doctest.testmod(sys.modules[__name__]) diff --git a/commands/lib/layman/db.py b/commands/lib/layman/db.py new file mode 100644 index 0000000..1baeabf --- /dev/null +++ b/commands/lib/layman/db.py @@ -0,0 +1,588 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN OVERLAY DB +################################################################################# +# File: db.py +# +# Access to the db of overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +'''Handles different storage files.''' + +__version__ = "$Id: db.py 309 2007-04-09 16:23:38Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +import os, codecs, os.path, urllib2, re, hashlib + +from layman.utils import path +from layman.overlay import Overlays + +from layman.debug import OUT + +#=============================================================================== +# +# Class DB +# +#------------------------------------------------------------------------------- + +class DB(Overlays): + ''' Handle the list of local overlays.''' + + def __init__(self, config): + + self.config = config + + self.path = config['local_list'] + + if config['nocheck']: + ignore = 2 + else: + ignore = 1 + + quiet = int(config['quietness']) < 3 + + Overlays.__init__(self, + [config['local_list'], ], + ignore, + quiet) + + OUT.debug('DB handler initiated', 6) + + def add(self, overlay, quiet = False): + ''' + Add an overlay to the local list of overlays. + + >>> write = os.tmpnam() + >>> write2 = os.tmpnam() + >>> write3 = os.tmpnam() + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> config = {'local_list' : + ... here + '/tests/testfiles/global-overlays.xml', + ... 'make_conf' : write2, + ... 'nocheck' : True, + ... 'storage' : write3, + ... 'quietness':3} + + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> a = DB(config) + >>> config['local_list'] = write + >>> b = DB(config) + >>> OUT.color_off() + + >>> m = MakeConf(config, b.overlays) + >>> m.path = write2 + >>> m.write() + + Commented out since it needs network access: + + # >>> b.add(a.select('wrobel-stable')) #doctest: +ELLIPSIS + # * Running command "/usr/bin/rsync -rlptDvz --progress --delete --delete-after --timeout=180 --exclude="distfiles/*" --exclude="local/*" --exclude="packages/*" "rsync://gunnarwrobel.de/wrobel-stable/*" "/tmp/file.../wrobel-stable""... + # >>> c = Overlays([write, ]) + # >>> c.overlays.keys() + # [u'wrobel-stable'] + + # >>> m = MakeConf(config, b.overlays) + # >>> [i.name for i in m.overlays] #doctest: +ELLIPSIS + # [u'wrobel-stable'] + + + # >>> os.unlink(write) + >>> os.unlink(write2) + >>> import shutil + + # >>> shutil.rmtree(write3) + ''' + + if overlay.name not in self.overlays.keys(): + result = overlay.add(self.config['storage'], quiet) + if result == 0: + if 'priority' in self.config.keys(): + overlay.set_priority(self.config['priority']) + self.overlays[overlay.name] = overlay + self.write(self.path) + make_conf = MakeConf(self.config, self.overlays) + make_conf.add(overlay) + else: + raise Exception('Adding the overlay failed! Possible remains of' + ' the opration have NOT been removed and may be' + ' left at ' + path([self.config['storage'], + overlay.name]) + '. Please re' + 'move them manually if required.') + else: + raise Exception('Overlay "' + overlay.name + '" already in the loca' + 'l list!') + + def delete(self, overlay): + ''' + Add an overlay to the local list of overlays. + + >>> write = os.tmpnam() + >>> write2 = os.tmpnam() + >>> write3 = os.tmpnam() + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> config = {'local_list' : + ... here + '/tests/testfiles/global-overlays.xml', + ... 'make_conf' : write2, + ... 'nocheck' : True, + ... 'storage' : write3, + ... 'quietness':3} + + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> a = DB(config) + >>> config['local_list'] = write + >>> b = DB(config) + >>> OUT.color_off() + + >>> m = MakeConf(config, b.overlays) + >>> m.path = here + '/tests/testfiles/make.conf' + >>> m.read() + + >>> m.path = write2 + >>> m.write() + + # >>> b.add(a.select('wrobel-stable')) #doctest: +ELLIPSIS + # * Running command "/usr/bin/rsync -rlptDvz --progress --delete --delete-after --timeout=180 --exclude="distfiles/*" --exclude="local/*" --exclude="packages/*" "rsync://gunnarwrobel.de/wrobel-stable/*" "/tmp/file.../wrobel-stable""... + # >>> b.add(a.select('wrobel')) #doctest: +ELLIPSIS + # * Running command "/usr/bin/svn co "https://overlays.gentoo.org/svn/dev/wrobel/" "/tmp/file.../wrobel""... + # >>> c = Overlays([write, ]) + # >>> c.overlays.keys() + # [u'wrobel', u'wrobel-stable'] + + # >>> b.delete(b.select('wrobel')) + # >>> c = Overlays([write, ]) + # >>> c.overlays.keys() + # [u'wrobel-stable'] + + # >>> m = MakeConf(config, b.overlays) + # >>> [i.name for i in m.overlays] #doctest: +ELLIPSIS + # [u'wrobel-stable'] + + # >>> os.unlink(write) + >>> os.unlink(write2) + >>> import shutil + + # >>> shutil.rmtree(write3) + ''' + + if overlay.name in self.overlays.keys(): + make_conf = MakeConf(self.config, self.overlays) + overlay.delete(self.config['storage']) + del self.overlays[overlay.name] + self.write(self.path) + make_conf.delete(overlay) + else: + raise Exception('No local overlay named "' + overlay.name + '"!') + + def sync(self, overlay_name, quiet = False): + '''Synchronize the given overlay.''' + + overlay = self.select(overlay_name) + + if overlay: + result = overlay.sync(self.config['storage'], quiet) + if result: + raise Exception('Syncing overlay "' + overlay_name + + '" returned status ' + str(result) + '!') + else: + raise Exception('No such overlay ("' + overlay_name + '")!') + +#=============================================================================== +# +# Class RemoteDB +# +#------------------------------------------------------------------------------- + +class RemoteDB(Overlays): + '''Handles fetching the remote overlay list.''' + + def __init__(self, config): + + self.config = config + + self.proxies = {} + + if config['proxy']: + self.proxies['http'] = config['proxy'] + elif os.getenv('http_proxy'): + self.proxies['http'] = os.getenv('http_proxy') + + if self.proxies: + proxy_handler = urllib2.ProxyHandler(self.proxies) + opener = urllib2.build_opener(proxy_handler) + urllib2.install_opener(opener) + + self.urls = [i.strip() for i in config['overlays'].split('\n') if i] + + paths = [self.path(i) for i in self.urls] + + if config['nocheck']: + ignore = 2 + else: + ignore = 0 + + quiet = int(config['quietness']) < 3 + + Overlays.__init__(self, paths, ignore, quiet) + + def cache(self): + ''' + Copy the remote overlay list to the local cache. + + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> cache = os.tmpnam() + >>> config = {'overlays' : + ... 'file://' + here + '/tests/testfiles/global-overlays.xml', + ... 'cache' : cache, + ... 'nocheck' : True, + ... 'proxy' : None, + ... 'quietness':3} + >>> a = RemoteDB(config) + >>> a.cache() + >>> b = open(a.path(config['overlays'])) + >>> b.readlines()[24] + ' A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org].\\n' + + >>> b.close() + >>> os.unlink(a.path(config['overlays'])) + + >>> a.overlays.keys() + [u'wrobel', u'wrobel-stable'] + ''' + for url in self.urls: + + mpath = self.path(url) + + try: + + # Fetch the remote list + olist = urllib2.urlopen(url).read() + + # Create our storage directory if it is missing + if not os.path.exists(os.path.dirname(mpath)): + try: + os.makedirs(os.path.dirname(mpath)) + except OSError, error: + raise OSError('Failed to create layman storage direct' + + 'ory ' + os.path.dirname(mpath) + '\n' + + 'Error was:' + str(error)) + + # Before we overwrite the old cache, check that the downloaded + # file is intact and can be parsed + try: + self.read(olist) + except Exception, error: + raise IOError('Failed to parse the overlays list fetched fr' + 'om ' + url + '\nThis means that the download' + 'ed file is somehow corrupt or there was a pr' + 'oblem with the webserver. Check the content ' + 'of the file. Error was:\n' + str(error)) + + # Ok, now we can overwrite the old cache + try: + out_file = open(mpath, 'w') + out_file.write(olist) + out_file.close() + + except Exception, error: + raise IOError('Failed to temporarily cache overlays list in' + ' ' + mpath + '\nError was:\n' + str(error)) + + + except IOError, error: + OUT.warn('Failed to update the overlay list from: ' + + url + '\nError was:\n' + str(error)) + + try: + # Finally parse the contents of the cache + self.read_file(mpath) + except IOError, error: + OUT.warn('Failed to read a cached version of the overlay list f' + 'rom ' + url + '. You probably did not download the fi' + 'le before. The corresponding entry in your layman.cfg' + ' file will be disregarded.\nError was:\n' + str(error) + ) + + def path(self, url): + '''Return a unique file name for the url.''' + + base = self.config['cache'] + + OUT.debug('Generating cache path.', 6) + + return base + '_' + hashlib.md5(url).hexdigest() + '.xml' + +#=============================================================================== +# +# Helper class MakeConf +# +#------------------------------------------------------------------------------- + +class MakeConf: + ''' + Handles modifications to /etc/make.conf + + Check that an add/remove cycle does not modify the make.conf: + + >>> import hashlib + >>> write = os.tmpnam() + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> config = {'local_list' : + ... here + '/tests/testfiles/global-overlays.xml', + ... 'make_conf' : here + '/tests/testfiles/make.conf', + ... 'nocheck' : True, + ... 'storage' : '/usr/portage/local/layman', + ... 'quietness':3} + >>> b = DB(config) + >>> a = MakeConf(config, b.overlays) + >>> o_md5 = str(hashlib.md5(open(here + '/tests/testfiles/make.conf').read()).hexdigest()) + >>> a.path = write + >>> a.add(b.overlays['wrobel-stable']) + >>> [i.name for i in a.overlays] + [u'wrobel-stable', u'wrobel-stable'] + >>> a.add(b.overlays['wrobel']) + >>> [i.name for i in a.overlays] + [u'wrobel', u'wrobel-stable', u'wrobel-stable'] + >>> a.delete(b.overlays['wrobel-stable']) + >>> [i.name for i in a.overlays] + [u'wrobel'] + >>> a.add(b.overlays['wrobel-stable']) + >>> [i.name for i in a.overlays] + [u'wrobel', u'wrobel-stable'] + >>> a.delete(b.overlays['wrobel']) + >>> n_md5 = str(hashlib.md5(open(write).read()).hexdigest()) + >>> o_md5 == n_md5 + True + >>> os.unlink(write) + ''' + + my_re = re.compile('PORTDIR_OVERLAY\s*=\s*"([^"]*)"') + + def __init__(self, config, overlays): + + self.path = config['make_conf'] + self.storage = config['storage'] + self.data = '' + self.db = overlays + self.overlays = [] + self.extra = [] + + self.read() + + def add(self, overlay): + ''' + Add an overlay to make.conf. + + >>> write = os.tmpnam() + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> config = {'local_list' : + ... here + '/tests/testfiles/global-overlays.xml', + ... 'make_conf' : here + '/tests/testfiles/make.conf', + ... 'nocheck' : True, + ... 'storage' : '/usr/portage/local/layman', + ... 'quietness':3} + >>> c = DB(config) + >>> a = MakeConf(config, c.overlays) + >>> a.path = write + >>> a.add(c.select('wrobel')) + >>> config['make_conf'] = write + >>> b = MakeConf(config, c.overlays) + >>> [i.name for i in b.overlays] + [u'wrobel', u'wrobel-stable'] + >>> b.extra + [u'/usr/portage/local/ebuilds/testing', u'/usr/portage/local/ebuilds/stable', u'/usr/portage/local/kolab2', u'/usr/portage/local/gentoo-webapps-overlay/experimental', u'/usr/portage/local/gentoo-webapps-overlay/production-ready'] + + >>> os.unlink(write) + ''' + self.overlays.append(overlay) + self.write() + + def delete(self, overlay): + ''' + Delete an overlay from make.conf. + + >>> write = os.tmpnam() + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> config = {'local_list' : + ... here + '/tests/testfiles/global-overlays.xml', + ... 'make_conf' : here + '/tests/testfiles/make.conf', + ... 'nocheck' : True, + ... 'storage' : '/usr/portage/local/layman', + ... 'quietness':3} + >>> c = DB(config) + >>> a = MakeConf(config, c.overlays) + >>> a.path = write + >>> a.delete(c.select('wrobel-stable')) + >>> config['make_conf'] = write + >>> b = MakeConf(config, c.overlays) + >>> [i.name for i in b.overlays] + [] + >>> b.extra + [u'/usr/portage/local/ebuilds/testing', u'/usr/portage/local/ebuilds/stable', u'/usr/portage/local/kolab2', u'/usr/portage/local/gentoo-webapps-overlay/experimental', u'/usr/portage/local/gentoo-webapps-overlay/production-ready'] + + >>> os.unlink(write) + ''' + self.overlays = [i + for i in self.overlays + if i.name != overlay.name] + self.write() + + def read(self): + ''' + Read the list of registered overlays from /etc/make.conf. + + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> config = {'local_list' : + ... here + '/tests/testfiles/global-overlays.xml', + ... 'make_conf' : here + '/tests/testfiles/make.conf', + ... 'nocheck' : True, + ... 'storage' : '/usr/portage/local/layman', + ... 'quietness':3} + >>> c = DB(config) + >>> a = MakeConf(config, c.overlays) + >>> [i.name for i in a.overlays] + [u'wrobel-stable'] + >>> a.extra + [u'/usr/portage/local/ebuilds/testing', u'/usr/portage/local/ebuilds/stable', u'/usr/portage/local/kolab2', u'/usr/portage/local/gentoo-webapps-overlay/experimental', u'/usr/portage/local/gentoo-webapps-overlay/production-ready'] + ''' + if os.path.isfile(self.path): + self.content() + + overlays = self.my_re.search(self.data) + + if not overlays: + raise Exception('Did not find a PORTDIR_OVERLAY entry in file ' + + self.path +'! Did you specify the correct file?') + + overlays = [i.strip() + for i in overlays.group(1).split('\n') + if i.strip()] + + for i in overlays: + if i[:len(self.storage)] == self.storage: + oname = os.path.basename(i) + if oname in self.db.keys(): + self.overlays.append(self.db[oname]) + else: + # These are additional overlays that we dont know + # anything about. The user probably added them manually + self.extra.append(i) + else: + # These are additional overlays that we dont know anything + # about. The user probably added them manually + self.extra.append(i) + + + else: + self.overlays = [] + self.data = 'PORTDIR_OVERLAY="\n"\n' + + self.extra = [i for i in self.extra + if (i != '$PORTDIR_OVERLAY' + and i != '${PORTDIR_OVERLAY}')] + + def write(self): + ''' + Write the list of registered overlays to /etc/make.conf. + + >>> write = os.tmpnam() + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> config = {'local_list' : + ... here + '/tests/testfiles/global-overlays.xml', + ... 'make_conf' : here + '/tests/testfiles/make.conf', + ... 'nocheck' : True, + ... 'storage' : '/usr/portage/local/layman', + ... 'quietness':3} + >>> c = DB(config) + >>> a = MakeConf(config, c.overlays) + >>> a.path = write + >>> a.write() + >>> config['make_conf'] = write + >>> b = MakeConf(config, c.overlays) + >>> [i.name for i in b.overlays] + [u'wrobel-stable'] + >>> b.extra + [u'/usr/portage/local/ebuilds/testing', u'/usr/portage/local/ebuilds/stable', u'/usr/portage/local/kolab2', u'/usr/portage/local/gentoo-webapps-overlay/experimental', u'/usr/portage/local/gentoo-webapps-overlay/production-ready'] + + >>> os.unlink(write) + ''' + def prio_sort(a, b): + '''Sort by priority.''' + if a.priority < b.priority: + return -1 + elif a.priority > b.priority: + return 1 + return 0 + + self.overlays.sort(prio_sort) + + paths = [] + for i in self.overlays: + paths.append(path((self.storage, i.name, ))) + + overlays = 'PORTDIR_OVERLAY="\n' + overlays += '\n'.join(paths) + '\n' + overlays += '$PORTDIR_OVERLAY\n' + overlays += '\n'.join(self.extra) + overlays += '"' + + content = self.my_re.sub(overlays, self.data) + + if not self.my_re.search(content): + raise Exception('Ups, failed to set a proper PORTDIR_OVERLAY entry ' + 'in file ' + self.path +'! Did not overwrite the fi' + 'le.') + + try: + make_conf = codecs.open(self.path, 'w', 'utf-8') + + make_conf.write(content) + + make_conf.close() + + except Exception, error: + raise Exception('Failed to read "' + self.path + '".\nError was:\n' + + str(error)) + + def content(self): + ''' + Returns the content of the /etc/make.conf file. + ''' + try: + make_conf = codecs.open(self.path, 'r', 'utf-8') + + self.data = make_conf.read() + + make_conf.close() + + except Exception, error: + raise Exception('Failed to read "' + self.path + '".\nError was:\n' + + str(error)) + +#=============================================================================== +# +# Testing +# +#------------------------------------------------------------------------------- + +if __name__ == '__main__': + import doctest, sys + + # Ignore warnings here. We are just testing + from warnings import filterwarnings, resetwarnings + filterwarnings('ignore') + + doctest.testmod(sys.modules[__name__]) + + resetwarnings() diff --git a/commands/lib/layman/debug.py b/commands/lib/layman/debug.py new file mode 100644 index 0000000..c5cf3a0 --- /dev/null +++ b/commands/lib/layman/debug.py @@ -0,0 +1,507 @@ +################################################################################# +# LAYMAN - DEBUGGING FUNCTIONS +################################################################################# +# debug.py -- Utility function for debugging +# Copyright 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 + +__version__ = "$Id: debug.py 153 2006-06-05 06:03:16Z wrobel $" + +################################################################################# +## +## Dependancies +## +################################################################################# + +import sys, inspect, types + +from optparse import OptionGroup + +################################################################################# +## +## Color codes (taken from portage) +## +################################################################################# + +esc_seq = '\x1b[' + +codes = {} +codes['reset'] = esc_seq + '39;49;00m' +codes['red'] = esc_seq + '31;01m' +codes['green'] = esc_seq + '32;01m' +codes['yellow'] = esc_seq + '33;01m' +codes['turquoise'] = esc_seq + '36;01m' + +################################################################################# +## +## Message Class +## +################################################################################# + +class Message: + #FIXME: Think about some simple doctests before you modify this class the + # next time. + + def __init__(self, module = '', + err = sys.stderr, + dbg = sys.stderr, + debugging_level = 4, + debugging_verbosity = 2, + info_level = 4, + warn_level = 4, + col = True, + mth = ['*'], + obj = ['*'], + var = ['*']): + + # A description of the module that is being debugged + self.debug_env = module + + # Where should the debugging output go? This can also be a file + self.debug_out = dbg + + # Where should the error output go? This can also be a file + self.error_out = err + + # The higher the level the more information you will get + self.warn_lev = warn_level + + # The higher the level the more information you will get + self.info_lev = info_level + + # The highest level of debugging messages acceptable for output + # The higher the level the more output you will get + self.debug_lev = debugging_level + + # The debugging output can range from very verbose (3) to + # very compressed (1) + self.debug_vrb = debugging_verbosity + + # Which methods should actually be debugged? + # Use '*' to indicate 'All methods' + self.debug_mth = mth + + # Which objects should actually be debugged? + # Use '*' to indicate 'All objects' + self.debug_obj = obj + + # Which variables should actually be debugged? + # Use '*' to indicate 'All variables' + self.debug_var = var + + # Exclude class variables by default + self.show_class_variables = False + + # Should the output be colored? + self.use_color = col + + self.has_error = False + + + ############################################################################ + # Add command line options + + def cli_opts(self, parser): + + group = OptionGroup(parser, + '', + 'Control the debugging features of ' + + self.debug_env) + + group.add_option('--debug', + action = 'store_true', + help = 'Activates debugging features.') + + group.add_option('--debug-level', + action = 'store', + type = 'int', + help = 'A value between 0 and 10. 0 means no debugging ' + 'messages will be selected, 10 selects all debugging me' + 'ssages. Default is "4".') + + group.add_option('--debug-verbose', + action = 'store', + type = 'int', + help = 'A value between 1 and 3. Lower values yield les' + 's verbose debugging output. Default is "2".') + + group.add_option('--debug-methods', + action = 'store', + help = 'Limits the methods that will return debugging o' + 'utput. The function name is sufficient and there is no' + 'difference between class methods or general functions.' + ' Several methods can be specified by seperating them w' + ' with a comma. Default is "*" which specifies all meth' + 'ods.') + + group.add_option('--debug-classes', + action = 'store', + help = 'Limits the classes that will return debugging o' + 'utput. Specify only the class name not including the m' + 'odules in which the class is defined (e.g. MyModule.ma' + 'in.Main should only be represented by "Main"). Several' + 'classes can be specified by seperating them with a com' + 'ma. Default is "*" which specifies all classes.') + + group.add_option('--debug-variables', + action = 'store', + help = 'Limits the variables that will return debugging' + ' output. Several variables can be specified by seperat' + 'ing them with a comma. Default is "*" which specifies ' + 'all variables.') + + group.add_option('--debug-class-vars', + action = 'store_true', + help = 'In default mode the debugging code will only re' + 'turn information on the local variable which does not ' + 'include the class variables. Use this switch to add al' + 'l values that are provided by "self".') + + group.add_option('--debug-nocolor', + action = 'store_true', + help = 'Deactivates colors in the debugging output.') + + parser.add_option_group(group) + + + ############################################################################# + # Handle command line options + + def cli_handle(self, options): + + if (options.__dict__.has_key('debug') + and options.__dict__['debug']): + self.debug_on() + else: + self.debug_off() + return + + if (options.__dict__.has_key('debug_class_vars') + and options.__dict__['debug_class_vars']): + self.class_variables_on() + else: + self.class_variables_off() + + if (options.__dict__.has_key('debug_nocolor') + and options.__dict__['debug_nocolor']): + self.color_off() + else: + self.color_on() + + if (options.__dict__.has_key('debug_level') and + options.__dict__['debug_level']): + dbglvl = int(options.__dict__['debug_level']) + if dbglvl < 0: + dbglvl = 0 + if dbglvl > 10: + dbglvl = 10 + self.set_debug_level(dbglvl) + + if (options.__dict__.has_key('debug_verbose') and + options.__dict__['debug_verbose']): + dbgvrb = int(options.__dict__['debug_verbose']) + if dbgvrb < 1: + dbgvrb = 1 + if dbgvrb > 3: + dbgvrb = 3 + self.set_debug_verbosity(dbgvrb) + + for i in [('debug_methods', self.set_debug_methods), + ('debug_classes', self.set_debug_classes), + ('debug_variables', self.set_debug_variables),]: + + if (options.__dict__.has_key(i[0]) and + options.__dict__[i[0]]): + i[1](options.__dict__[i[0]]) + + + ############################################################################# + ## Helper Functions + + def set_module(self, module): + + self.debug_env = module + + def set_debug_methods(self, methods): + + methods = methods.split(',') + + if methods: + self.debug_mth = methods + + def set_debug_classes(self, classes): + + classes = classes.split(',') + + if classes: + self.debug_obj = classes + + def set_debug_variables(self, variables): + + variables = variables.split(',') + + if variables: + self.debug_var = variables + + def maybe_color (self, col, text): + if self.use_color: + return codes[col] + text + codes['reset'] + return text + + def set_info_level(self, info_level = 4): + self.info_lev = info_level + + def info_off(self): + self.set_info_level(0) + + def info_on(self, info_level = 4): + self.set_info_level(info_level) + + def set_warn_level(self, warn_level = 4): + self.warn_lev = warn_level + + def warn_off(self): + self.set_warn_level(0) + + def warn_on(self, warn_level = 4): + self.set_warn_level(warn_level) + + def set_debug_level(self, debugging_level = 4): + self.debug_lev = debugging_level + + def set_debug_verbosity(self, debugging_verbosity = 2): + self.debug_vrb = debugging_verbosity + + def debug_off(self): + self.set_debug_level(0) + + def debug_on(self): + self.set_debug_level() + + def color_off(self): + self.use_color = False + + def color_on(self): + self.use_color = True + + def class_variables_off(self): + self.show_class_variables = False + + def class_variables_on(self): + self.show_class_variables = True + + ############################################################################# + ## Output Functions + + def notice (self, note): + print note + + def info (self, info, level = 4): + + if type(info) not in types.StringTypes: + info = str(info) + + if level > self.info_lev: + return + + for i in info.split('\n'): + print self.maybe_color('green', '* ') + i + + def status (self, message, status, info = 'ignored'): + + if type(message) not in types.StringTypes: + message = str(message) + + lines = message.split('\n') + + if not lines: + return + + for i in lines[0:-1]: + print self.maybe_color('green', '* ') + i + + i = lines[-1] + + if len(i) > 58: + i = i[0:57] + + if status == 1: + result = '[' + self.maybe_color('green', 'ok') + ']' + elif status == 0: + result = '[' + self.maybe_color('red', 'failed') + ']' + else: + result = '[' + self.maybe_color('yellow', info) + ']' + + print self.maybe_color('green', '* ') + i + ' ' + '.' * (58 - len(i)) \ + + ' ' + result + + def warn (self, warn, level = 4): + + if type(warn) not in types.StringTypes: + warn = str(warn) + + if level > self.warn_lev: + return + + for i in warn.split('\n'): + print self.maybe_color('yellow', '* ') + i + + def error (self, error): + + if type(error) not in types.StringTypes: + error = str(error) + + for i in error.split('\n'): + print >> self.error_out, self.maybe_color('red', '* ') + i + self.has_error = True + + def die (self, error): + + if type(error) not in types.StringTypes: + error = str(error) + + for i in error.split('\n'): + self.error(self.maybe_color('red', 'Fatal error: ') + i) + self.error(self.maybe_color('red', 'Fatal error(s) - aborting')) + sys.exit(1) + + def debug (self, message, level = 4): + ''' + This is a generic debugging method. + ''' + ## Check the debug level first. This is the most inexpensive check. + if level > self.debug_lev: + return + + ## Maybe this should be debugged. So get the stack first. + stack = inspect.stack() + + ## This can probably never happen but does not harm to check + ## that there is actually something calling this function + if len(stack) < 2: + return + + ## Get the stack length to determine indentation of the debugging output + stacklength = len(stack) + ls = ' ' * stacklength + + ## Get the information about the caller + caller = stack[1] + + ## The function name of the calling frame is the fourth item in the list + callermethod = caller[3] + + ## Is this actually one of the methods that should be debugged? + if not '*' in self.debug_mth and not callermethod in self.debug_mth: + return + + ## Still looks like this should be debugged. So retrieve the dictionary + ## of local variables from the caller + callerlocals = inspect.getargvalues(caller[0])[3] + + ## Is the caller an obejct? If so he provides 'self' + if 'self' in callerlocals.keys(): + callerobject = callerlocals['self'] + del callerlocals['self'] + if self.show_class_variables: + cv = inspect.getmembers(callerobject, + lambda x: not inspect.ismethod(x)) + callerlocals.sync(cv) + else: + callerobject = None + + # Remove variables not requested + if not '*' in self.debug_var: + callerlocals = dict([i for i in callerlocals.items() + if i[0] in self.debug_var]) + + ## Is the object among the list of objects to debug? + if (not '*' in self.debug_obj and + not str(callerobject.__class__.__name__) in self.debug_obj): + return + + if type(message) not in types.StringTypes: + message = str(message) + + def breaklines(x): + ''' + Helper function to keep width of the debugging output. + + This may look ugly for arrays but it is acceptable and not + breaking the line would break the output format + ''' + ## Get the number of lines we need (rounded down) + lines = len(x) // 60 + if lines > 0: + for j in range(lines): + ## Print line with continuation marker + print >> self.debug_out, ls + '// ' + x[0:60] + ' \\' + ## Remove printed characters from output + x = x[60:] + ## Print final line + print >> self.debug_out, ls + '// ' + x + + if self.debug_vrb == 1: + # Top line indicates class and method + c = '' + if callerobject: + c += 'Class: ' + str(callerobject.__class__.__name__) + ' | ' + if callermethod: + c += 'Method: ' + str(callermethod) + print >> self.debug_out, '// ' + c + # Selected variables follow + if callerlocals: + for i,j in callerlocals.items(): + print >> self.debug_out, '// ' \ + + self.maybe_color('turquoise', str(i)) + ':' + str(j) + # Finally the message + print >> self.debug_out, self.maybe_color('yellow', message) + return + + if self.debug_vrb == 3: + print >> self.debug_out, ls + '/////////////////////////////////' + \ + '////////////////////////////////' + + # General information about what is being debugged + #(module name or similar) + print >> self.debug_out, ls + '// ' + self.debug_env + print >> self.debug_out, ls + '//-----------------------------------' + \ + '----------------------------' + + ## If the caller is a class print the name here + if callerobject: + print >> self.debug_out, ls + \ + '// Object Class: ' + str(callerobject.__class__.__name__) + + ## If the method has been extracted print it here + if callermethod: + print >> self.debug_out, ls + '// ' \ + + self.maybe_color('green', 'Method: ') + str(callermethod) + if self.debug_vrb == 3: + print >> self.debug_out, ls + '//---------------------------' + \ + '------------------------------------' + + ## Print the information on all available local variables + if callerlocals: + if self.debug_vrb == 3: + print >> self.debug_out, ls + '//' + print >> self.debug_out, ls + '// VALUES ' + for i,j in callerlocals.items(): + print >> self.debug_out, ls + '// ------------------> ' \ + + self.maybe_color('turquoise', str(i)) + ':' + breaklines(str(j)) + if self.debug_vrb == 3: + print >> self.debug_out, ls + '//------------------------------'\ + '---------------------------------' + + # Finally print the message + breaklines(self.maybe_color('yellow', message)) + + if self.debug_vrb == 3: + print >> self.debug_out, ls + '//-------------------------------' + \ + '--------------------------------' + print >> self.debug_out, ls + '/////////////////////////////////' + \ + '////////////////////////////////' + +## gloabal message handler +OUT = Message('layman') diff --git a/commands/lib/layman/overlay.py b/commands/lib/layman/overlay.py new file mode 100644 index 0000000..fadb59d --- /dev/null +++ b/commands/lib/layman/overlay.py @@ -0,0 +1,244 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN OVERLAY HANDLER +################################################################################# +# File: overlay.py +# +# Access to an xml list of overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +'''Main handler for overlays.''' + +__version__ = "$Id: overlay.py 273 2006-12-30 15:54:50Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +import sys, codecs, os, os.path, xml.dom.minidom + +from layman.overlays.bzr import BzrOverlay +from layman.overlays.darcs import DarcsOverlay +from layman.overlays.git import GitOverlay +from layman.overlays.mercurial import MercurialOverlay +from layman.overlays.cvs import CvsOverlay +from layman.overlays.svn import SvnOverlay +from layman.overlays.rsync import RsyncOverlay +from layman.overlays.tar import TarOverlay + +from layman.debug import OUT + +#=============================================================================== +# +# Constants +# +#------------------------------------------------------------------------------- + +OVERLAY_TYPES = {'git' : GitOverlay, + 'cvs' : CvsOverlay, + 'svn' : SvnOverlay, + 'rsync' : RsyncOverlay, + 'tar' : TarOverlay, + 'bzr' : BzrOverlay, + 'mercurial' : MercurialOverlay, + 'darcs' : DarcsOverlay} + +#=============================================================================== +# +# Class Overlays +# +#------------------------------------------------------------------------------- + +class Overlays: + ''' Handle a list of overlays.''' + + def __init__(self, paths, ignore = 0, quiet = False): + + self.quiet = quiet + self.paths = paths + self.ignore = ignore + + self.overlays = {} + + OUT.debug('Initializing overlay list handler', 8) + + for path in self.paths: + if os.path.exists(path): + self.read_file(path) + + def read_file(self, path): + '''Read the overlay definition file.''' + + try: + document = open(path).read() + + except Exception, error: + raise IOError('Failed to read the overlay list at ("' + + path + '")!\nError was:\n' + str(error)) + + + self.read(document) + + def read(self, document): + ''' + Read an xml list of overlays. + + >>> here = os.path.dirname(os.path.realpath(__file__)) + + >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ]) + >>> a.overlays.keys() + [u'wrobel', u'wrobel-stable'] + + >>> a.overlays['wrobel-stable'].data['&src'] + u'rsync://gunnarwrobel.de/wrobel-stable' + ''' + try: + document = xml.dom.minidom.parseString(document) + + except Exception, error: + raise Exception('Failed to parse the overlay list!\nError was:\n' + + str(error)) + + overlays = document.getElementsByTagName('overlay') + + for overlay in overlays: + + OUT.debug('Parsing overlay entry', 8) + + for index in range(0, overlay.attributes.length): + attr = overlay.attributes.item(index) + if attr.name == 'type': + if attr.nodeValue in OVERLAY_TYPES.keys(): + try: + ovl = OVERLAY_TYPES[attr.nodeValue](overlay, + self.ignore, + self.quiet) + self.overlays[ovl.name] = ovl + except Exception, error: + OUT.warn(str(error), 3) + else: + raise Exception('Unknown overlay type "' + + attr.nodeValue + '"!') + + def write(self, path): + ''' + Write the list of overlays to a file. + + >>> write = os.tmpnam() + >>> here = os.path.dirname(os.path.realpath(__file__)) + + >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ]) + >>> b = Overlays([write,]) + >>> b.overlays['wrobel-stable'] = a.overlays['wrobel-stable'] + >>> b.write(write) + >>> c = Overlays([write,]) + >>> c.overlays.keys() + [u'wrobel-stable'] + + >>> os.unlink(write) + ''' + + imp = xml.dom.minidom.getDOMImplementation() + + doc = imp.createDocument('layman', 'overlays', None) + + root = doc.childNodes[0] + + for name, overlay in self.overlays.items(): + + root.appendChild(overlay.to_minidom(doc)) + + try: + + out_file = codecs.open(path, 'w', 'utf-8') + + doc.writexml(out_file, '', ' ', '\n') + + except Exception, error: + raise Exception('Failed to write to local overlays file: ' + + path + '\nError was:\n' + str(error)) + + def select(self, overlay): + ''' + Select an overlay from the list. + + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ]) + >>> a.select('wrobel-stable').data['&src'] + u'rsync://gunnarwrobel.de/wrobel-stable' + ''' + if overlay in self.overlays.keys(): + return self.overlays[overlay] + + def list(self, verbose = False, width = 0): + ''' + List all overlays. + + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ]) + >>> for i in a.list(True): + ... print i[0] + wrobel + ~~~~~~ + Source : https://overlays.gentoo.org/svn/dev/wrobel + Contact : nobody@gentoo.org + Type : Subversion; Priority: 10 + + Description: + Test + + wrobel-stable + ~~~~~~~~~~~~~ + Source : rsync://gunnarwrobel.de/wrobel-stable + Contact : nobody@gentoo.org + Type : Rsync; Priority: 50 + + Description: + A collection of ebuilds from Gunnar Wrobel [wrobel@gentoo.org]. + + + >>> for i in a.list(False, 80): + ... print i[0] + wrobel [Subversion] (https://o.g.o/svn/dev/wrobel ) + wrobel-stable [Rsync ] (rsync://gunnarwrobel.de/wrobel-stable) + ''' + result = [] + + for name, overlay in self.overlays.items(): + + if verbose: + result.append((str(overlay), overlay.is_supported(), + overlay.is_official())) + else: + result.append((overlay.short_list(width), overlay.is_supported(), + overlay.is_official())) + + result = sorted(result) + + return result + +#=============================================================================== +# +# Testing +# +#------------------------------------------------------------------------------- + +if __name__ == '__main__': + import doctest, sys + + # Ignore warnings here. We are just testing + from warnings import filterwarnings, resetwarnings + filterwarnings('ignore') + + doctest.testmod(sys.modules[__name__]) + + resetwarnings() diff --git a/commands/lib/layman/overlays/__init__.py b/commands/lib/layman/overlays/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/commands/lib/layman/overlays/__init__.py @@ -0,0 +1 @@ +# diff --git a/commands/lib/layman/overlays/bzr.py b/commands/lib/layman/overlays/bzr.py new file mode 100644 index 0000000..4c14278 --- /dev/null +++ b/commands/lib/layman/overlays/bzr.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN BZR OVERLAY HANDLER +################################################################################# +# File: bzr.py +# +# Handles bzr overlays +# +# Copyright: +# (c) 2005 - 2008 Adrian Perez, Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Adrian Perez +# Gunnar Wrobel +# +'''Should work with any version of Bzr equal to or better than 0.7 -- + caution: tested only with 0.8 and 0.8.2...''' + +__version__ = "$Id: bzr.py 236 2006-09-05 20:39:37Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class BzrOverlay +# +#------------------------------------------------------------------------------- + +class BzrOverlay(Overlay): + ''' Handles bzr overlays.''' + + type = 'Bzr' + + binary_command = '/usr/bin/bzr' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + return self.cmd(self.binary_command + ' get "' + self.src + '/" "' +\ + path([base, self.name]) + '"') + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + return self.cmd('cd "' + path([base, self.name]) + '" && ' + \ + self.binary_command + ' pull --overwrite "' + self.src \ + + '"') + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary_command, 'bzr', + 'dev-util/bzr'),]) diff --git a/commands/lib/layman/overlays/cvs.py b/commands/lib/layman/overlays/cvs.py new file mode 100644 index 0000000..096dfea --- /dev/null +++ b/commands/lib/layman/overlays/cvs.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN CVS OVERLAY HANDLER +################################################################################# +# File: cvs.py +# +# Handles cvs overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +''' Cvs overlay support.''' + +__version__ = "$Id$" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class CvsOverlay +# +#------------------------------------------------------------------------------- + +class CvsOverlay(Overlay): + ''' Handles cvs overlays.''' + + type = 'cvs' + + binary = '/usr/bin/cvs' + + def __init__(self, xml, ignore = 0, quiet = False): + + Overlay.__init__(self, xml, ignore, quiet) + + if '&subpath' in self.data.keys(): + self.subpath = self.data['&subpath'] + else: + self.subpath = '' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + if quiet: + quiet_option = ' -q' + else: + quiet_option = '' + + return self.cmd('cd "' + base + '" && CVSROOT="' + self.src + '" ' + + self.binary + quiet_option + ' co -d "' + self.name + + '" "' + self.subpath + '"' ) + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + if quiet: + quiet_option = ' -q' + else: + quiet_option = '' + + return self.cmd('cd "' + path([base, self.name]) + '" && ' + + self.binary + quiet_option + ' update') + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary, 'cvs', + 'dev-util/cvs'),]) diff --git a/commands/lib/layman/overlays/darcs.py b/commands/lib/layman/overlays/darcs.py new file mode 100644 index 0000000..0d27d5e --- /dev/null +++ b/commands/lib/layman/overlays/darcs.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN DARCS OVERLAY HANDLER +################################################################################# +# File: darcs.py +# +# Handles darcs overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel, Andres Loeh +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# Andres Loeh +# +''' Darcs overlay support.''' + +__version__ = "$Id: darcs.py 236 2006-09-05 20:39:37Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class BzrOverlay +# +#------------------------------------------------------------------------------- + +class DarcsOverlay(Overlay): + ''' Handles darcs overlays.''' + + type = 'Darcs' + + binary_command = '/usr/bin/darcs' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + return self.cmd(self.binary_command + ' get --partial "' + self.src + + '/" "' + path([base, self.name]) + '"') + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + return self.cmd('cd "' + path([base, self.name]) + '" && ' + + self.binary_command + ' pull --all "' + self.src + '"') + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary_command, 'darcs', + 'dev-util/darcs'),]) diff --git a/commands/lib/layman/overlays/git.py b/commands/lib/layman/overlays/git.py new file mode 100644 index 0000000..bda2df0 --- /dev/null +++ b/commands/lib/layman/overlays/git.py @@ -0,0 +1,77 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN GIT OVERLAY HANDLER +################################################################################# +# File: git.py +# +# Handles git overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel, Stefan Schweizer +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# Stefan Schweizer +''' Git overlay support.''' + +__version__ = "$Id: git.py 146 2006-05-27 09:52:36Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class GitOverlay +# +#------------------------------------------------------------------------------- + +class GitOverlay(Overlay): + ''' Handles git overlays.''' + + type = 'Git' + + binary_command = '/usr/bin/git' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + if quiet: + quiet_option = '-q ' + else: + quiet_option = '' + + # http:// should get trailing slash, other protocols shouldn't + slash = '' + if self.src.split(':')[0] == 'http': + slash = '/' + return self.cmd(self.binary_command + ' clone ' + quiet_option + '"' + self.src + slash + + '" "' + path([base, self.name]) + '"') + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + if quiet: + quiet_option = ' -q' + else: + quiet_option = '' + + return self.cmd('cd "' + path([base, self.name]) + '" && ' + + self.binary_command + ' pull' + quiet_option) + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary_command, 'git', + 'dev-util/git'),]) diff --git a/commands/lib/layman/overlays/mercurial.py b/commands/lib/layman/overlays/mercurial.py new file mode 100644 index 0000000..b010c8b --- /dev/null +++ b/commands/lib/layman/overlays/mercurial.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN MERCURIAL OVERLAY HANDLER +################################################################################# +# File: darcs.py +# +# Handles darcs overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel, Andres Loeh +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# Andres Loeh +# +''' Mercurial overlay support.''' + +__version__ = "$Id: mercurial.py 236 2006-09-05 20:39:37Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class MercurialOverlay +# +#------------------------------------------------------------------------------- + +class MercurialOverlay(Overlay): + ''' Handles mercurial overlays.''' + + type = 'Mercurial' + + binary_command = '/usr/bin/hg' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + return self.cmd(self.binary_command + ' clone "' + self.src + '/" "' + + path([base, self.name]) + '"') + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + return self.cmd('cd "' + path([base, self.name]) + '" && ' + + self.binary_command + ' pull -u "' + self.src + '"') + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary_command, 'mercurial', + 'dev-util/mercurial'),]) diff --git a/commands/lib/layman/overlays/overlay.py b/commands/lib/layman/overlays/overlay.py new file mode 100644 index 0000000..b9568b1 --- /dev/null +++ b/commands/lib/layman/overlays/overlay.py @@ -0,0 +1,301 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN OVERLAY BASE CLASS +################################################################################# +# File: overlay.py +# +# Base class for the different overlay types. +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +''' Basic overlay class.''' + +__version__ = "$Id: overlay.py 273 2006-12-30 15:54:50Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +import sys, types, re, os, os.path, shutil, subprocess + +from layman.utils import node_to_dict, dict_to_node, path + +from layman.debug import OUT + +#=============================================================================== +# +# Class Overlay +# +#------------------------------------------------------------------------------- + +class Overlay: + ''' Derive the real implementations from this.''' + + type = 'None' + + def __init__(self, xml, ignore = 0, quiet = False): + ''' + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read() + >>> import xml.dom.minidom + >>> document = xml.dom.minidom.parseString(document) + >>> overlays = document.getElementsByTagName('overlay') + >>> a = Overlay(overlays[0]) + >>> a.name + u'wrobel' + >>> a.is_official() + True + >>> a.src + u'https://overlays.gentoo.org/svn/dev/wrobel' + >>> a.contact + u'nobody@gentoo.org' + >>> a.description + u'Test' + >>> a.priority + 10 + >>> b = Overlay(overlays[1]) + >>> b.is_official() + False + ''' + self.quiet = quiet + + self.data = node_to_dict(xml) + + if '&name' in self.data.keys(): + self.name = self.data['&name'] + else: + raise Exception('Overlay is missing a "name" attribute!') + + if '&src' in self.data.keys(): + self.src = self.data['&src'] + else: + raise Exception('Overlay "' + self.name + '" is missing a "src" ' + 'attribute!') + + if '&contact' in self.data.keys(): + self.contact = self.data['&contact'] + else: + self.contact = '' + if not ignore: + raise Exception('Overlay "' + self.name + '" is missing a ' + '"contact" attribute!') + elif ignore == 1: + OUT.warn('Overlay "' + self.name + '" is missing a ' + '"contact" attribute!', 4) + + if '1' in self.data.keys(): + self.description = self.data['1']['@'].strip() + else: + self.description = '' + if not ignore: + raise Exception('Overlay "' + self.name + '" is missing a ' + '"description" entry!') + elif ignore == 1: + OUT.warn('Overlay "' + self.name + '" is missing a ' + '"description" entry!', 4) + + if '&status' in self.data.keys(): + self.status = self.data['&status'] + else: + self.status = '' + + if '&priority' in self.data.keys(): + self.priority = int(self.data['&priority']) + else: + self.priority = 50 + + def set_priority(self, priority): + '''Set the priority of this overlay.''' + + self.data['&priority'] = str(priority) + self.priority = int(priority) + + def to_minidom(self, document): + '''Convert to xml.''' + + return dict_to_node(self.data, document, 'overlay') + + def add(self, base, quiet = False): + '''Add the overlay.''' + + mdir = path([base, self.name]) + + if os.path.exists(mdir): + raise Exception('Directory ' + mdir + ' already exists. Will not ov' + 'erwrite its contents!') + + os.makedirs(mdir) + + def sync(self, base, quiet = False): + '''Sync the overlay.''' + pass + + def delete(self, base): + '''Delete the overlay.''' + mdir = path([base, self.name]) + + if not os.path.exists(mdir): + raise Exception('Directory ' + mdir + ' does not exist. Cannot remo' + 've the overlay!') + + shutil.rmtree(mdir) + + def cmd(self, command): + '''Run a command.''' + + OUT.info('Running command "' + command + '"...', 2) + + if hasattr(sys.stdout,'encoding'): + enc = sys.stdout.encoding or sys.getfilesystemencoding() + if enc: + command = command.encode(enc) + + if not self.quiet: + return os.system(command) + else: + cmd = subprocess.Popen([command], shell = True, + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + close_fds = True) + result = cmd.wait() + return result + + def __str__(self): + ''' + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read() + >>> import xml.dom.minidom + >>> document = xml.dom.minidom.parseString(document) + >>> overlays = document.getElementsByTagName('overlay') + >>> a = Overlay(overlays[0]) + >>> print str(a) + wrobel + ~~~~~~ + Source : https://overlays.gentoo.org/svn/dev/wrobel + Contact : nobody@gentoo.org + Type : None; Priority: 10 + + Description: + Test + + ''' + + result = u'' + + result += self.name + u'\n' + (len(self.name) * u'~') + + result += u'\nSource : ' + self.src + result += u'\nContact : ' + self.contact + result += u'\nType : ' + self.type + result += u'; Priority: ' + str(self.priority) + u'\n' + + description = self.description + description = re.compile(u' +').sub(u' ', description) + description = re.compile(u'\n ').sub(u'\n', description) + result += u'\nDescription:' + result += u'\n '.join((u'\n' + description).split(u'\n')) + result += u'\n' + + if '1' in self.data.keys(): + link = self.data['1']['@'].strip() + link = re.compile(u' +').sub(u' ', link) + link = re.compile(u'\n ').sub(u'\n', link) + result += u'\nLink:\n' + result += u'\n '.join((u'\n' + link).split(u'\n')) + result += u'\n' + + return result + + def short_list(self, width = 0): + ''' + >>> here = os.path.dirname(os.path.realpath(__file__)) + >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read() + >>> import xml.dom.minidom + >>> document = xml.dom.minidom.parseString(document) + >>> overlays = document.getElementsByTagName('overlay') + >>> a = Overlay(overlays[0]) + >>> print a.short_list(80) + wrobel [None ] (https://o.g.o/svn/dev/wrobel ) + ''' + + def pad(string, length): + '''Pad a string with spaces.''' + if len(string) <= length: + return string + ' ' * (length - len(string)) + else: + return string[:length - 3] + '...' + + def terminal_width(): + '''Determine width of terminal window.''' + try: + width = int(os.environ['COLUMNS']) + if width > 0: + return width + except: + pass + try: + import struct, fcntl, termios + query = struct.pack('HHHH', 0, 0, 0, 0) + response = fcntl.ioctl(1, termios.TIOCGWINSZ, query) + width = struct.unpack('HHHH', response)[1] + if width > 0: + return width + except: + pass + return 80 + + name = pad(self.name, 25) + mtype = ' [' + pad(self.type, 10) + ']' + if not width: + width = terminal_width() + srclen = width - 43 + source = self.src + if len(source) > srclen: + source = source.replace("overlays.gentoo.org", "o.g.o") + source = ' (' + pad(source, srclen) + ')' + + return name + mtype + source + + def supported(self, binaries = []): + '''Is the overlay type supported?''' + + if binaries: + for mpath, mtype, package in binaries: + if not os.path.exists(mpath): + raise Exception('Binary ' + mpath + ' seems to be missing!' + ' Overlay type "' + mtype + '" not support' + 'ed. Did you emerge ' + package + '?') + + return True + + def is_supported(self): + '''Is the overlay type supported?''' + + try: + self.supported() + return True + except Exception, error: + return False + + def is_official(self): + '''Is the overlay official?''' + + return self.status == 'official' + +#================================================================================ +# +# Testing +# +#-------------------------------------------------------------------------------- + +if __name__ == '__main__': + import doctest, sys + doctest.testmod(sys.modules[__name__]) diff --git a/commands/lib/layman/overlays/rsync.py b/commands/lib/layman/overlays/rsync.py new file mode 100644 index 0000000..6052bd0 --- /dev/null +++ b/commands/lib/layman/overlays/rsync.py @@ -0,0 +1,73 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN RSYNC OVERLAY HANDLER +################################################################################# +# File: rsync.py +# +# Handles rsync overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +''' Rsync overlay support.''' + +__version__ = "$Id: rsync.py 236 2006-09-05 20:39:37Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class RsyncOverlay +# +#------------------------------------------------------------------------------- + +class RsyncOverlay(Overlay): + ''' Handles rsync overlays.''' + + type = 'Rsync' + + binary = '/usr/bin/rsync' + + base = binary + ' -rlptDvz --progress --delete --delete-after ' + \ + '--timeout=180 --exclude="distfiles/*" --exclude="local/*" ' + \ + '--exclude="packages/*" ' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + Overlay.add(self, base) + + return self.sync(base) + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + if quiet: + quiet_option = '-q ' + else: + quiet_option = '' + + return self.cmd(self.base + quiet_option + '"' + self.src + '/" "' + + path([base, self.name]) + '"') + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary, 'rsync', + 'net-misc/rsync'),]) diff --git a/commands/lib/layman/overlays/svn.py b/commands/lib/layman/overlays/svn.py new file mode 100644 index 0000000..4ff3da4 --- /dev/null +++ b/commands/lib/layman/overlays/svn.py @@ -0,0 +1,75 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN SVN OVERLAY HANDLER +################################################################################# +# File: svn.py +# +# Handles subversion overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +''' Subversion overlay support.''' + +__version__ = "$Id: svn.py 236 2006-09-05 20:39:37Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class SvnOverlay +# +#------------------------------------------------------------------------------- + +class SvnOverlay(Overlay): + ''' Handles subversion overlays.''' + + type = 'Subversion' + + binary = '/usr/bin/svn' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + Overlay.add(self, base) + + if quiet: + quiet_option = '-q ' + else: + quiet_option = '' + + return self.cmd(self.binary + ' co ' + quiet_option + '"' + self.src + '/" "' + + path([base, self.name]) + '"') + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + if quiet: + quiet_option = '-q ' + else: + quiet_option = '' + + return self.cmd(self.binary + ' up ' + quiet_option + '"' + path([base, self.name]) + + '"') + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary, 'svn', + 'dev-util/subversion'),]) diff --git a/commands/lib/layman/overlays/tar.py b/commands/lib/layman/overlays/tar.py new file mode 100644 index 0000000..5786931 --- /dev/null +++ b/commands/lib/layman/overlays/tar.py @@ -0,0 +1,189 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN TAR OVERLAY HANDLER +################################################################################# +# File: tar.py +# +# Handles tar overlays +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# +''' Tar overlay support.''' + +__version__ = "$Id: tar.py 310 2007-04-09 16:30:40Z wrobel $" + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +import os, os.path, sys, urllib2, shutil + +from layman.utils import path +from layman.overlays.overlay import Overlay + +#=============================================================================== +# +# Class TarOverlay +# +#------------------------------------------------------------------------------- + +class TarOverlay(Overlay): + ''' Handles tar overlays. + + A dummy tar handler that overwrites the __init__ method + so that we don't need to provide xml input: + + >>> from layman.debug import OUT + >>> class DummyTar(TarOverlay): + ... def __init__(self): + ... self.name = 'dummy' + ... here = os.path.dirname(os.path.realpath(__file__)) + ... self.src = 'file://' + here + '/../tests/testfiles/layman-test.tar.bz2' + ... self.subpath = 'layman-test' + ... self.format = 'bz2' + ... self.quiet = False + >>> testdir = os.tmpnam() + >>> os.mkdir(testdir) + >>> a = DummyTar() + >>> OUT.color_off() + >>> a.add(testdir) #doctest: +ELLIPSIS + * Running command "/bin/tar -v -x -j -f... + >>> sorted(os.listdir(testdir + '/dummy')) + ['app-admin', 'app-portage'] + >>> shutil.rmtree(testdir) + ''' + + type = 'Tar' + + binary = u'/bin/tar' + + def __init__(self, xml, ignore = 0, quiet = False): + + Overlay.__init__(self, xml, ignore) + + if '&format' in self.data.keys(): + self.format = self.data['&format'] + else: + self.format = '' + + if '&subpath' in self.data.keys(): + self.subpath = self.data['&subpath'] + else: + self.subpath = '' + + if '&category' in self.data.keys(): + if self.subpath: + raise Exception('Cannot use "category" and "subpath" at the same' + ' time!') + + self.category = self.data['&category'] + else: + self.category = '' + + def add(self, base, quiet = False): + '''Add overlay.''' + + self.supported() + + mdir = path([base, self.name]) + + if os.path.exists(mdir): + raise Exception('Directory ' + mdir + ' already exists. Will not ov' + 'erwrite its contents!') + + if self.format == 'bz2' or (not self.format and self.src[-3:] == 'bz2'): + ext = 'bz2' + opt = '-j' + elif self.format == 'gz' or (not self.format and self.src[-2:] == 'gz'): + ext = 'gz' + opt = '-z' + else: + raise Exception('Unsupported file format!') + + try: + + tar = urllib2.urlopen(self.src).read() + + except Exception, error: + raise Exception('Failed to fetch the tar package from: ' + + self.src + '\nError was:' + str(error)) + + pkg = path([base, self.name + '.tar.' + ext]) + + try: + + out_file = open(pkg, 'w') + out_file.write(tar) + out_file.close() + + except Exception, error: + raise Exception('Failed to store tar package in ' + + pkg + '\nError was:' + str(error)) + + if self.subpath: + target = path([base, 'tmp']) + else: + if self.category: + target = mdir + '/' + self.category + else: + target = mdir + + os.makedirs(target) + + result = self.cmd(self.binary + u' -v -x ' + opt + u' -f "' + pkg + + u'" -C "' + target + u'"') + + if self.subpath: + source = target + '/' + self.subpath + if os.path.exists(source): + try: + os.rename(source, mdir) + except Exception, error: + raise Exception('Failed to rename tar subdirectory ' + + source + ' to ' + mdir + '\nError was:' + + str(error)) + else: + raise Exception('Given subpath "' + source + '" does not exist ' + ' in the tar package!') + try: + shutil.rmtree(target) + except Exception, error: + raise Exception('Failed to remove unnecessary tar structure "' + + target + '"\nError was:' + str(error)) + + os.unlink(pkg) + + return result + + def sync(self, base, quiet = False): + '''Sync overlay.''' + + self.supported() + + self.delete(base) + + self.add(base) + + def supported(self): + '''Overlay type supported?''' + + return Overlay.supported(self, [(self.binary, 'tar', 'app-arch/tar'), ]) + +if __name__ == '__main__': + import doctest + + # Ignore warnings here. We are just testing + from warnings import filterwarnings, resetwarnings + filterwarnings('ignore') + + doctest.testmod(sys.modules[__name__]) + + resetwarnings() diff --git a/commands/lib/layman/utils.py b/commands/lib/layman/utils.py new file mode 100644 index 0000000..178ad11 --- /dev/null +++ b/commands/lib/layman/utils.py @@ -0,0 +1,208 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# POLYMERAZE XML UTILITIES +################################################################################# +# File: xml.py +# +# Utilities to deal with xml nodes. +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# + +'''Utility functions to deal with xml nodes. ''' + +__version__ = '$Id: utils.py 236 2006-09-05 20:39:37Z wrobel $' + +#=============================================================================== +# +# Dependencies +# +#------------------------------------------------------------------------------- + +import types, re + +#=============================================================================== +# +# Helper functions +# +#------------------------------------------------------------------------------- + +def node_to_text(node): + ''' + Reduces an xml node to its text elements. The function does not + collect the text nodes recursively. + + >>> import xml.dom.minidom + >>> imp = xml.dom.minidom.getDOMImplementation() + >>> doc = imp.createDocument('test', 'root', None) + >>> root = doc.childNodes[0] + >>> node = doc.createTextNode('text') + >>> a = root.appendChild(node) + >>> node = doc.createElement('text') + >>> node2 = doc.createTextNode('text') + >>> a = node.appendChild(node2) + >>> a = root.appendChild(node) + >>> node = doc.createTextNode('text') + >>> a = root.appendChild(node) + >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS + '...texttexttext' + + >>> node_to_text(root) + 'texttext' + + ''' + text = '' + + for child in node.childNodes: + if child.nodeType == child.TEXT_NODE: + text = text + child.data + + return text + +def node_to_dict(node): + ''' Converts a xml node to a dictionary. The function collects the + nodes recursively. Attributes will be prepended with '&', child + nodes will be surrounded with tags. An index will be appended + since several child nodes with the same tag may exist. Text + elements will be collapsed and stored in a n entry prepended with + '@'. Comments will be ignored. + + >>> import xml.dom.minidom + >>> imp = xml.dom.minidom.getDOMImplementation() + >>> doc = imp.createDocument('test', 'root', None) + >>> root = doc.childNodes[0] + >>> node = doc.createTextNode('text') + >>> a = root.appendChild(node) + >>> node = doc.createElement('text') + >>> node2 = doc.createTextNode('text') + >>> comm = doc.createComment('comment') + >>> attr = doc.createAttribute('&attr') + >>> a = node.appendChild(node2) + >>> a = root.appendChild(comm) + >>> node.setAttributeNode(attr) + >>> node.setAttribute('&attr','test') + >>> a = root.appendChild(node) + >>> node3 = doc.createElement('text') + >>> a = root.appendChild(node3) + >>> node = doc.createTextNode('text') + >>> a = root.appendChild(node) + >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS + '...texttexttext' + + >>> node_to_dict(root) + {'1': {'@': 'text', '&&attr': 'test'}, '2': {'@': ''}, '@': 'texttext'} + + ''' + result = {} + + # Map the attributes + for index in range(0, node.attributes.length): + attr = node.attributes.item(index) + result['&' + attr.name] = attr.nodeValue + + text = '' + + # Map the nodes + for child in node.childNodes: + if child.nodeType == child.TEXT_NODE: + text = text + child.data + if child.nodeType == child.ELEMENT_NODE: + index = 1 + while ('<' + child.tagName + '>' + str(index)) in result.keys(): + index += 1 + result['<' + child.tagName + '>' + str(index)] = node_to_dict(child) + + result['@'] = text + + return result + +def dict_to_node(data, document, root_name): + ''' Reverts the node_to_dict operation. + + >>> import xml.dom.minidom + >>> imp = xml.dom.minidom.getDOMImplementation() + >>> doc = imp.createDocument('test', 'root', None) + >>> a = {'1': {'@': 'text', '&&attr': 'test'}, '2': {'@': ''}, '@': 'texttext'} + >>> doc.childNodes[0] = dict_to_node(a, doc, 'root') + >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS + '...texttexttext' + + ''' + node = document.createElement(root_name) + + for i, j in data.items(): + + if i[0] == '&': + attr = document.createAttribute(i[1:]) + node.setAttributeNode(attr) + node.setAttribute(i[1:], j) + if i[0] == '<': + k = i[1:] + while k[-1] in '0123456789': + k = k[:-1] + child = dict_to_node(data[i], + document, + k[:-1]) + node.appendChild(child) + if i[0] == '@': + child = document.createTextNode(j) + node.appendChild(child) + + return node + +def path(path_elements): + ''' + Concatenate a path from several elements. + + >>> path([]) + '' + >>> path(['a']) + 'a' + >>> path(['a','b']) + 'a/b' + >>> path(['a/','b']) + 'a/b' + >>> path(['/a/','b']) + '/a/b' + >>> path(['/a/','b/']) + '/a/b' + >>> path(['/a/','b/']) + '/a/b' + >>> path(['/a/','/b/']) + '/a/b' + >>> path(['/a/','/b','c/']) + '/a/b/c' + ''' + pathname = '' + + if type(path_elements) in types.StringTypes: + path_elements = [path_elements] + + # Concatenate elements and seperate with / + for i in path_elements: + pathname += i + '/' + + # Replace multiple consecutive slashes + pathname = re.compile('/+').sub('/', pathname) + + # Remove the final / if there is one + if pathname and pathname[-1] == '/': + pathname = pathname[:-1] + + return pathname + +#=============================================================================== +# +# Testing +# +#------------------------------------------------------------------------------- + +if __name__ == '__main__': + import doctest, sys + doctest.testmod(sys.modules[__name__]) diff --git a/commands/lib/layman/version.py b/commands/lib/layman/version.py new file mode 100644 index 0000000..a366b47 --- /dev/null +++ b/commands/lib/layman/version.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +################################################################################# +# LAYMAN VERSION +################################################################################# +# File: version.py +# +# Current version number +# +# Copyright: +# (c) 2005 - 2008 Gunnar Wrobel +# Distributed under the terms of the GNU General Public License v2 +# +# Author(s): +# Gunnar Wrobel +# + +__version__ = "$Id: version.py 309 2007-04-09 16:23:38Z wrobel $" + + +VERSION = '1.2.3' + +if __name__ == '__main__': + print VERSION diff --git a/commands/manage_layman.py b/commands/manage_layman.py new file mode 100644 index 0000000..a490c0a --- /dev/null +++ b/commands/manage_layman.py @@ -0,0 +1,72 @@ +from subprocess import call + +from commands import getstatusoutput + +import sys, ConfigParser, os.path, re + +from layman.config import Config +from layman.action import * +from layman.db import DB + +here = os.path.split(os.path.realpath(__file__))[0] + +class LaymanManager: + def AddAll(self): + """add overlays and sync them""" + + command1 = "./layman -c mylayman.cfg -a ALL" + print command1 + (status, output) = getstatusoutput(command1) + print status + print output + + """ + command2 = "./layman -c mylayman.cfg -s ALL" + getstatusoutput(command2) + + print command1, "\n", command2 + """ + + def List(self): + """return overlays dict""" + + sys.argv.append('-c') + sys.argv.append('mylayman.cfg') + config = Config() + + """ + l = ListLocal(a) + l.run() + """ + + db = DB(config) + overlays = dict() + + for name, overlay in db.overlays.items(): + overlays[name] = dict() + overlays[name]["src"] = overlay.src + overlays[name]["contact"] = overlay.contact + + description = overlay.description + description = re.compile(u' +').sub(u' ', description) + description = re.compile(u'\n ').sub(u'\n', description) + + overlays[name]["description"] = description + + if '1' in overlay.data.keys(): + link = overlay.data['1']['@'].strip() + link = re.compile(u' +').sub(u' ', link) + link = re.compile(u'\n ').sub(u'\n', link) + else: + link = "" + + overlays[name]["link"] = link + return overlays + +def main(): + h = LaymanManager() + h.AddAll() + overlays = h.List() + +if __name__ == '__main__': + main() diff --git a/commands/mylayman.cfg b/commands/mylayman.cfg new file mode 100644 index 0000000..d0ddbfa --- /dev/null +++ b/commands/mylayman.cfg @@ -0,0 +1,58 @@ +[MAIN] + +#----------------------------------------------------------- +# Defines the directory where overlays should be installed + +storage : /home/timemachine/www/ebuildfnd/ebuildfind/commands/var/ + +#----------------------------------------------------------- +# Remote overlay lists will be stored here +# layman will append _md5(url).xml to each filename + +cache : %(storage)s/cache + +#----------------------------------------------------------- +# The list of locally installed overlays + +local_list: /home/timemachine/www/ebuildfnd/ebuildfind/commands/overlays.xml + +#----------------------------------------------------------- +# Path to the make.conf file that should be modified by +# layman + +make_conf : %(storage)s/make.conf + +#----------------------------------------------------------- +# URLs of the remote lists of overlays (one per line) or +# local overlay definitions +# +#overlays : http://www.gentoo.org/proj/en/overlays/layman-global.txt +# http://dev.gentoo.org/~wrobel/layman/global-overlays.xml +# http://mydomain.org/my-layman-list.xml +# file:///usr/portage/local/layman/my-list.xml + +overlays : file:///home/timemachine/www/ebuildfnd/ebuildfind/commands/overlays.txt + +#----------------------------------------------------------- +# Proxy support +# +#proxy : http://[user:pass@]www.my-proxy.org:3128 + +#----------------------------------------------------------- +# Strict checking of overlay definitions +# +# Set either to "yes" or "no". If "no" layman will issue +# warnings if an overlay definition is missing either +# description or contact information. +# +nocheck : yes + +#----------------------------------------------------------- +# Umask settings +# +# layman should usually work with a umask of 0022. You should +# only change this setting if you are absolutely certain that +# you know what you are doing. +# +#umask : 0022 + diff --git a/commands/overlays.txt b/commands/overlays.txt new file mode 100644 index 0000000..3f246d9 --- /dev/null +++ b/commands/overlays.txt @@ -0,0 +1,1232 @@ + + + + https://overlays.gentoo.org/dev/betelgeuse + Betelgeuse's developer overlay + + + http://repo.or.cz/w/gentoo-lisp-overlay.git + Common Lisp/Scheme development, recruitment and + live overlay. Support and feedback in `#gentoo-lisp' and via + `gentoo-lisp@gentoo.org'. + + + http://roslin.mlodyinteligent.pl/ + This is roslin, my small overlay. Enjoy! + (: + + + http://s3d.berlios.de/ + Gentoo ebuilds for s3d and related packages. s3d + is a 3d network display server which can be used as 3d desktop + enviroment. + + + Experimental overlay for desktop effects + packages. + + + Experimental overlay for .NET + packages. + + + Packages for players and authors of interactive + fiction + + + Gentoo ebuild overlay with misc stuff that I find + interesting. + + + Experimental overlay for zen related + packages. + + + Miscellaneous ebuilds not yet in + portage + + + Linux Terminal Server Project + overlay + + + Arcon Overlay! + http://code.google.com/p/arcon/ + + + http://www.thepetersclan.net + This is a Gnash ( flash player ) cvs and snapshot + overlay. + + + http://overlays.gentoo.org/dev/aross + Personal scratch space. + + + http://overlays.gentoo.org/dev/dirtyepic + Various work-in-progress stuff including GCC-svn + and wxGTK. + + + http://overlays.gentoo.org/proj/xfce/wiki + Experimental ebuilds for the Xfce4 Desktop + Environment + + + http://overlays.gentoo.org/dev/je_fro + Helpful ebuilds for the macbook pro, and + experimental gentoo-science packages. + + + http://overlays.gentoo.org/dev/suka + experimental stuff of all sorts + + + http://luke.dashjr.org + Misc ebuilds by Luke-Jr + + + http://www.lila-center.info + The Lila theme is a community project, originally + created by Daniel G. Taylor and members of the Gentoo Linux + community. The theme is based around SVG graphics - which means + they can be scaled to any size without loss of quality - and is + meant to be usable across different desktops and platforms. For + more information about the Lila theme project or to see how you + could get involved, there are a few places to look: The Lila + theme forums #lila on chat.freenode.org + + + http://www.verlihub-project.org + Verlihub is a Direct Connect protocol server runs + on Linux OS written in C++; Many features are available: MySQL + database, very low use of CPU, RAM and Bandwidth, deflood + integrated protection, plugins + + + http://jyujin.de/ + eINIT, kyuuba, dev9, various splash + daemons + + + http://overlays.gentoo.org/proj/mozilla + New mozilla development that is not yet in + tree + + + http://overlays.gentoo.org/proj/science/wiki/en + The Gentoo Science Overlay is intended as a place + to work outside of the main portage tree on experimental + ebuilds. Our aim is to increase the rate of development of + scientific packages for Gentoo, but ebuilds in this repository + are by their very nature more experimental. If you wish to use + them you should be willing to help test and report + bugs. + + + + experimental gnome ebuilds + + + experimental gpe ebuilds + + + http://genkdesvn.mailstation.de + Paludis-only kde4 overlay. Unsupported by KDE team. + + + http://kde.gentoo.org + Official KDE team's testing overlay. + + + http://kde.gentoo.org + KDE 3 overlay + + + http://gentoo.zugaina.org/ + collection of ebuilds by ycarus + + + http://overlays.gentoo.org + This is the home of Gentoo's wider collection of + ebuilds for web-based applications. This is where we collect + all the ebuilds submitted to Bugzilla by our users, and make + them available in an easy-to-use overlay for wider + testing. + + + http://overlays.gentoo.org/dev/anant/wiki + A collection of ebuilds related to the D + programming language. + + + http://overlays.gentoo.org/dev/anant/wiki + A collection of useful ebuilds related to + Plan9. + + + http://git.xnull.de/gitweb/?p=overlay.git + A collection of work-in-progress ebuilds and other + fun broken things. + + + http://overlays.gentoo.org + A collection of stable ebuilds from Gunnar Wrobel + [wrobel@gentoo.org]. + + + http://www.gentoo.org/proj/en/kolab/index.xml + Project to allow running Kolab on + Gentoo. + + + http://armagetronad.net + 3D light cycles, like the movie TRON + + + http://games.gentoo.org/ + A collection of work-in-progress ebuilds and + ebuilds which require testing. + + + http://svn.netdomination.org/gentoo-voip + Voice over IP related ebuilds. + + + http://www.initng.org + Initng is a full replacement of the old and in + many ways deprecated sysvinit tool. It is designed with speed + in mind because it does as much as possible asynchronously. In + other words: It will boot your unix-system much faster, and + give you more control and statistics over your + system. + + + http://overlays.gentoo.org/proj/nx + Overlay for the NX/FreeNX packages for + Gentoo. + + + http://proaudio.tuxfamily.org/wiki + Evermind's overlay with ebuilds for a lot of + pro-audio production software. + + + http://pda.gentoo.ru + This overlay contains some pda-related ebuilds + (for now for devices such as iPAQ hx4700, Sharp Zaurus, Asus + a620 and some others) + + + http://bugs.gentoo.org/show_bug.cgi?id=122500 + Testing ground for vmware-server and + vmware-server-console ebuilds until they can eventually be + committed into portage. + + + http://sabayonlinux.org + Purpose To provide ebuilds that were created from + the Sabayon Linux project such as customized programs, ebuilds + not in the official portage, artwork, themes, etc. Bugs to + http://bugs.sabayonlinux.org/bugs/ + + + http://code.google.com/p/gentoo-china-overlay + Purpose To provide some programs useful to Chinese + users. + + + http://overlays.gentoo.org/proj/java + The only java overlay available via layman. This + overlays contains ebuilds that are expected to work when you + emerge them. The ebuilds also need to use the generation 2 + eclasses. + + + + http://overlays.gentoo.org/proj/java/wiki/GCJ_as_a_JDK + An overlay for GCJ to use as a Java SDK / + RE. + + + http://blog.flameeyes.eu/ + Flameeyes' private developer overlay + + + http://www.gentoo.org/proj/en/desktop/x/x11/ + Gentoo X11 team overlay + + + http://dev.gentoo.org/~dberkholz/overlay/ + Donnie Berkholz's private developer + overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/loki_val.git;a=summary + Peter Alfredsen's private developer + overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/darkside.git;a=summary + Jeremy Olexa's (darkside) private developer + overlay + + + http://drizzt.bsdnet.eu/ + drizzt's private developer overlay + + + http://overlays.gentoo.org/dev/trapni/ + trapni's private developer overlay (mostly + covering YaCS/server related ebuilds for now) + + + http://overlays.gentoo.org/proj/sunrise + Ebuilds for bugs assigned to + maintainer-wanted + + + http://overlays.gentoo.org + A collection of stable ebuilds from Wolfram + Schlich [wschlich@gentoo.org]. + + + http://overlays.gentoo.org + A collection of testing ebuilds from Wolfram + Schlich [wschlich@gentoo.org]. + + + http://overlays.gentoo.org + Some ebuilds not yet ready for mainstream portage + from Thilo Bangert [bangert@gentoo.org]. + + + http://overlays.gentoo.org + Some ebuilds not yet ready for mainstream portage + from Tobias Scherbaum [dertobi123@gentoo.org]. + + + http://overlays.gentoo.org/proj/vps + Gentoo VPS project overlay (experimental + ebuilds) + + + http://www.hboeck.de + Purpose To provide new Xgl and AIGLX desktop + developments as mentioned on his blog. + + + http://www.hboeck.de + Hanno Boeck developer overlay. + + + http://geki.ath.cx/index.php/OpenOffice + Purpose Unsupported openoffice version with + experimental patchset + + + http://overlays.gentoo.org + Mostly Python-related ebuilds. + + + http://overlays.gentoo.org/proj/python/wiki + Python development tree, staging area for the tree. + + + http://overlays.gentoo.org/proj/python/wiki + Python experimental tree. + + + http://overlays.gentoo.org + Development overlay for ebuilds that I plan to + commit to the tree that are sourced from bugzilla or + liquidx. + + + http://gentoo-taiwan.googlecode.com/ + A collection of ebuilds from Gentoo + Taiwan. + + + http://dev.gentoo.org/~dev-zero/ + Dev-zeros personal developer overlay + + + http://overlays.gentoo.org/dev/genstef + Genstef's Overlay - It usually contains some + experimental ebuilds on their way to the tree + + + http://overlays.gentoo.org/dev/jokey + Jokey's Overlay - Contains pre-tree stuff like + italc, pkgcore-test-ebuilds and lcd stuff + + + http://overlays.gentoo.org/dev/chtekk + Overlay for various applications I use myself and + plan on adding to the tree or update/fix. + + + http://overlays.gentoo.org/dev/chtekk + Development overlay for a SysCP (syscp.org) ebuild + and Gentoo port, as well as additional + patches/features. + + + http://overlays.gentoo.org/proj/mysql + Development overlay for MySQL, testing + branch. + + + http://overlays.gentoo.org/proj/php + Contains a copy of everything + dev-lang/php-4*-related, which can no longer be kept in the + official tree for security reasons. + + + http://overlays.gentoo.org/proj/php + Development overlay for PHP, testing + branch. + + + http://overlays.gentoo.org/proj/php + Development overlay for PHP, experimental + branch. + + + http://overlays.gentoo.org/proj/postgresql + Development overlay for PostgreSQL, testing + branch. + + + http://overlays.gentoo.org/proj/postgresql + Development overlay for PostgreSQL, experimental + branch. + + + http://n4g.mars.arge.at + The goal for this overlay is to reproduce the Open + Enterprise server from novell on gentoo + + + http://n4g.mars.arge.at + The goal for this overlay is to reproduce the Open + Enterprise server from novell on gentoo + + + + http://mpd.wikia.com/wiki/Repositories#Experimental_Gentoo_Overlay + The experimental gentoo overlay was designed as a + way to keep up-to-date. Most of it are live ebuilds, ebuilds + that pull the latest HEAD from whatever repository. It also + includes ebuilds for clients that are not yet in portage. It is + maintained by avuton, send new ebuilds, corrections or bugs + directly to him. + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/halcy0n.git;a=summary + Various packages, probably some toolchain stuff + though + + + http://www.haskell.org/~gentoo/gentoo-haskell/ + The Official Gentoo Haskell overlay. + + + http://opensvn.csie.org/rmh3093/iwlwifi + This overlay provides ebuilds for the new wireless + driver iwlwifi + + + http://scm.calivia.com/svn/sipx/gentoo + This repository contains sipx and related + ebuilds. + + + http://overlays.gentoo.org/proj/vdr + Development overlay for VDR, testing + branch. + + + http://overlays.gentoo.org/proj/vdr + Overlay for VDR, that contains ebuilds for + development version of VDR, and specific plugins for that + version. + + + http://overlays.gentoo.org/proj/vdr + Development overlay for VDR, experimental branch. + WARNING: This branch can kill your VDR! Only use it if you know + what you are doing. It is best to stay in touch with the + developers if you would like to try this out. We are available + in #gentoo-vdr on Freenode. + + + http://overlays.gentoo.org/proj/vdr + Overlay for VDR, that contains ebuilds for + the vdr-xine output plugin, and the needed patched xine-lib + + + + http://nouveau.freedesktop.org/ + Experimental ebuilds for the free nouveau driver + for nvidia cards. + + + Temporary overlay for adding support for the EFIKA + platform to Gentoo. + + + http://overlays.gentoo.org/dev/seemant + Seemant's development overlay for django and other + things. + + + + http://overlays.gentoo.org/dev/vapier/wiki/enlightenment + Support for the Enlightenment project, most + notably DR17/e17. + + + http://overlays.gentoo.org/proj/toolchain/wiki + Toolchain ebuilds that are unsuitable for the + tree. Snapshots, unstable versions, etc... + + + http://dev.gentoo.org/~serkan + Serkan Kaba's (serkan) private developer + overlay + + + http://gentoo.xwing.info + This overlay contains some experimental stuff, + such as turboprint printers driver (bug #61311), intel-536ep + driver for lastest 2.6 kernels (bug #127464), lastest grisbi + version (proxy maintainer) before it's portage integration and + so on. + + + http://svn.digital-trauma.de/gentoo/ + This overlay has a binary, current version of + eclipse with many plugins and some small new ebuilds from + trauma and bugzilla.g.o. + + + http://overlays.gentoo.org + Experimental ebuilds from the private overlay of + Ioannis Aslanidis [deathwing00@gentoo.org]. + + + http://overlays.gentoo.org/dev/marineam + Experimental ebuilds for Xen. + + + http://overlays.gentoo.org/proj/xen + Experimental ebuilds for Xen. + + + http://overlays.gentoo.org/proj/cell + Support for Cell architecture, including IBM blade + and Sony Playstation 3 + + + http://overlays.gentoo.org/proj/powerpc + Support for PowerPC-based ebuilds that are not + appropriate for the portage tree. + + + http://overlays.gentoo.org/proj/emacs/ + Provide Emacs related ebuilds which are a bit + experimental or work-in-progress. Don't rely on them, but don't + hesitate to file bugs or write emails. + + + http://overlays.gentoo.org/proj/emacs/ + Provide XEmacs related ebuilds which are a bit + experimental or work-in-progress. Don't rely on them, but don't + hesitate to file bugs or write emails. + + + http://blog.pioto.org + Most things in here are still works in progress or + not stable enough for the main ebuild tree. If something + breaks, you're on your own. + + + http://overlays.gentoo.org/dev/matsuu/ + Matsuu's Second Life Overlay + + + http://overlays.gentoo.org/proj/gnustep + Experimental ebuilds for GNUstep packages in + Gentoo. Comments and bugreports are welcome! + + + http://overlays.gentoo.org/proj/rox + Experimental ebuilds for the Rox + Desktop. + + + http://overlays.gentoo.org/proj/perl/ + Experimental ebuilds for Perl packages in Gentoo. + Comments and bugreports are welcome! + + + http://svn.liveforge.org/berkano/trunk + Berkano overlay provides an overlay for Gentoo + Linux with ebuilds of bleeding edge software (such as live + subversion builds) and other handy tools that are missing from + the official portage tree. Areas of interest include multimedia + and system administration. + + + http://www.freevo.org + The Freevo overlay provides ebuils for development + snapshots of the unreleased Freevo 2.0 and its + dependencies. + + + http://dev.gentoo.org/~swegener/ + This overlay contains some experimental stuff, but + mostly stuff I quickly wrote an ebuild for or grabed it from + bugzilla and did not have the time to commit it to the official + tree or do not consider it ready for it. + + + http://genkdesvn.mailstation.de + A collection of work-in-progress ebuilds and other + fun broken things. + + + http://overlays.gentoo.org/dev/rbu/wiki + Random stuff. + + + http://moving-innovations.com/blog/ + Developer overlay of Hans de Graaff with mostly + ruby and xemacs ebuilds, and a few assorted other + goodies. + + + http://devnull.core.ws/EbuildRepository/ + Various ebuilds, most of them are bleeding edge + scm versions, the others have not found their way into portage + yet. + + + http://pd-overlay.sourceforge.net/ + Subversion ebuilds for PureData the dataflow + language + + + http://overlays.gentoo.org/proj/finnish + Finnish overlay for spell checking etc. + etc. + + + http://overlays.gentoo.org/dev/lu_zero + Experimental Media and PowerPC/CELL related + ebuilds. + + + + http://cafarelli.fr/websvn/listing.php?repname=voyageur-overlay + Voyageur's random ebuilds stuff + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/uberlord;a=summary + Uberlord's openrc ebuilds + + + http://dev.gentoo.org/~hawking/ + hawking's random ebuilds. + + + http://dev.gentoo.org/~hwoarang/ + hwoarangs' testing ebuilds + + + http://overlays.gentoo.org/proj/gcc-porting/ + Compatibility patches for upcoming GCC + releases. + + + http://dev.gentoo.org/~falco/ + Falco's random stuff about netmon, net-mail or + security, unofficial ebuilds like proxsmtp, unofficial patches + on Postfix; also pre-stable security upgrades, perhaps merged + in the Security Overlay Project some day. + + + http://www.mavrinac.com/index.cgi?page=tp + Overlay for the Thousand Parsec framework for + turn-based space empire building games. + + + Kernel Virtual Machine userspace + support + + + http://ebuild.gentoo.gr.jp/ + GentooJP provides custom ebuilds for Japanese + Gentoo users. + + + https://trac.poildetroll.net/trac/akoya + Akoya overlay + + + http://gentoo-wiki.com/Howto_OSS4 + OSSv4 overlay + + + http://overlays.gentoo.org/proj/ruby/wiki + Experimental ebuilds from the Ruby + edge. + + + http://dev.gentoo.org/~mueli + Overlay which provides the bleeding edge on the + kerberos integration in gentoo. + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/ikelos.git;a=summary + Ikelos's hospice for broken and damaged + ebuilds. + + + http://www.wolf31o2.org + Wolf31o2's project ebuilds + + + http://www.gentoo.org/proj/en/desktop/lxde/ + Repo for development of ebuilds for the LXDE + desktop environment. + + + http://os-rostov.ru/ + Repo for development of ebuilds. + + + http://www.lordvan.com + LordVan's project ebuilds + + + + http://github.com/eatnumber1/pcsx2-overlay/tree/master + Experimental overlay for pcsx2 + ebuilds. + + + + http://sugarlabs.org/go/Community/Distributions/Gentoo + Sugar (sugarlabs.org) related + packages + + + + http://overlays.gentoo.org/proj/embedded/wiki/openmoko + Openmoko's project overlay. + + + https://launchpad.net/bzr-gentoo-overlay/ + A collection of Bazaar-related ebuilds, including + release candidates of Bazaar. + + + http://github.com/gentoo-qt/qting-edge/ + Experimental Qt4 ebuilds and related packages, + provided by Gentoo's Qt team. The overlay contains ebuilds for + official pre-releases, and live ebuilds for both the official + Nokia Qt Software git repository and KDE's qt-copy subversion + repository. It also has various (non-KDE) packages that use + Qt4. + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/alexxy.git + Some random work in progress stuff from + alexxy + + + + http://dev.openbossa.org/trac/mamona/wiki/MamonaGentooOverlay + Mamona is an embedded Linux distribution, based on + Open Embedded, for ARM EABI. + + + http://www.gentoo-quebec.org + New ebuilds created by the Gentoo-Quebec + team. + + + https://overlays.gentoo.org/dev/mescalinum + Tcl/Tk multi-slot system, with tcltk eselect module + for switching across multiple versions (actually: 8.4 8.5 8.6) + + + + http://git.goodpoint.de/?p=overlay-sping.git;a=summary + Gentoo overlay of Sebastian Pipping + + + http://github.com/steev/steev-overlay/tree/master + Steev Klimaszewski's Overlay + + + http://repo.or.cz/w/otih-overlay.git + Otih's Provide-Patches Overlay + + + https://overlays.gentoo.org/dev/mescalinum + Tcl/Tk 8.8, Itcl/Itk 4 (beta) and other fixed packages + + + + http://wiki.cregion.ru/moin.cgi/CRG_Overlay + CRG-Overlay for Gentoo Linux + + + http://gitorious.org/projects/tante_overlay/repos/mainline + Overlay of tante + + + http://code.google.com/p/raw/ + some raw stuff + + + http://repo.or.cz/w/gentoo-overlay-ibormuth.git + Personal Overlay of Ingo Bormuth + + + + http://git.overlays.gentoo.org/gitweb/?p=proj/m68k.git + m68k team overlay + + + + http://repo.or.cz/w/dottout.git + + Dottout overlay + + + + http://repo.or.cz/w/ub0rlay.git + + This is an ub0r overlay! + + + + http://git.overlays.gentoo.org/gitweb/?p=proj/gentoo-bsd.git + Gentoo/BSD Project Overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/maekke.git + Markus Meier developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/scarabeus.git + Tomas Chvatal developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/nirbheek.git + Nirbheek Chauhan developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/leio.git + Mart Raudsepp developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/remi.git + Remi Cardona developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/jmbsvicetto.git + Jorge Manuel B. S. Vicetto developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/tove.git + Torsten Veller developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/pchrist.git + Panagiotis Christopoulos developer overlay + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/matsuu.git + MATSUU Takuto developer overlay + + + + http://code.google.com/p/rion-overlay/ + Russian ovelay with a some patched and specific software + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/dagger.git;a=summary + Dagger developer overlay + + + + http://slonopotamus.org/gentoo-on-n8x0 + + Packages to support Nokia Internet Tablets (N8x0) + + + + diff --git a/commands/overlays.xml b/commands/overlays.xml new file mode 100644 index 0000000..d3dc486 --- /dev/null +++ b/commands/overlays.xml @@ -0,0 +1,2999 @@ + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/maekke.git + + + + + Markus Meier developer overlay + + + + + + + + + + + + + + + http://www.mavrinac.com/index.cgi?page=tp + + + + + Overlay for the Thousand Parsec framework for + turn-based space empire building games. + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/xen + + + + + Experimental ebuilds for Xen. + + + + + + + + + + + + + + + http://jyujin.de/ + + + + + eINIT, kyuuba, dev9, various splash + daemons + + + + + + + + + + + + + + + http://kde.gentoo.org + + + + + Official KDE team's testing overlay. + + + + + + + + + + + + + + + http://www.lordvan.com + + + + + LordVan's project ebuilds + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/rox + + + + + Experimental ebuilds for the Rox + Desktop. + + + + + + + + + + + + + + + + http://code.google.com/p/rion-overlay/ + + + + + Russian ovelay with a some patched and specific software + + + + + + + + + + + + + + + http://www.thepetersclan.net + + + + + This is a Gnash ( flash player ) cvs and snapshot + overlay. + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/php + + + + + Contains a copy of everything + dev-lang/php-4*-related, which can no longer be kept in the + official tree for security reasons. + + + + + + + + + + + + + + + http://os-rostov.ru/ + + + + + Repo for development of ebuilds. + + + + + + + + + + + + + + + http://roslin.mlodyinteligent.pl/ + + + + + This is roslin, my small overlay. Enjoy! + (: + + + + + + + + + + + + + + + http://kde.gentoo.org + + + + + KDE 3 overlay + + + + + + + + + + + + + + + http://repo.or.cz/w/otih-overlay.git + + + + + Otih's Provide-Patches Overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/postgresql + + + + + Development overlay for PostgreSQL, testing + branch. + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/xfce/wiki + + + + + Experimental ebuilds for the Xfce4 Desktop + Environment + + + + + + + + + + + + + + + + http://sugarlabs.org/go/Community/Distributions/Gentoo + + + + + Sugar (sugarlabs.org) related + packages + + + + + + + + + + + + + + + http://pd-overlay.sourceforge.net/ + + + + + Subversion ebuilds for PureData the dataflow + language + + + + + + + + + + + + + + + http://geki.ath.cx/index.php/OpenOffice + + + + + Purpose Unsupported openoffice version with + experimental patchset + + + + + + + + + + + + + Experimental overlay for desktop effects + packages. + + + + + + + + + + + + + + + http://overlays.gentoo.org + + + + + A collection of stable ebuilds from Gunnar Wrobel + [wrobel@gentoo.org]. + + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/vapier/wiki/enlightenment + + + + + Support for the Enlightenment project, most + notably DR17/e17. + + + + + + + + + + + + + + + http://drizzt.bsdnet.eu/ + + + + + drizzt's private developer overlay + + + + + + + + + + + + + + + + http://slonopotamus.org/gentoo-on-n8x0 + + + + + + Packages to support Nokia Internet Tablets (N8x0) + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/loki_val.git;a=summary + + + + + Peter Alfredsen's private developer + overlay + + + + + + + + + + + + + + + + http://mpd.wikia.com/wiki/Repositories#Experimental_Gentoo_Overlay + + + + + The experimental gentoo overlay was designed as a + way to keep up-to-date. Most of it are live ebuilds, ebuilds + that pull the latest HEAD from whatever repository. It also + includes ebuilds for clients that are not yet in portage. It is + maintained by avuton, send new ebuilds, corrections or bugs + directly to him. + + + + + + + + + + + + + + + http://www.gentoo-quebec.org + + + + + New ebuilds created by the Gentoo-Quebec + team. + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/uberlord;a=summary + + + + + Uberlord's openrc ebuilds + + + + + + + + + + + + + + + http://gentoo.zugaina.org/ + + + + + collection of ebuilds by ycarus + + + + + + + + + + + + + + + http://dev.gentoo.org/~dberkholz/overlay/ + + + + + Donnie Berkholz's private developer + overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org + + + + + A collection of testing ebuilds from Wolfram + Schlich [wschlich@gentoo.org]. + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/darkside.git;a=summary + + + + + Jeremy Olexa's (darkside) private developer + overlay + + + + + + + + + + + + + Miscellaneous ebuilds not yet in + portage + + + + + + + + + + + + + + + + http://dev.openbossa.org/trac/mamona/wiki/MamonaGentooOverlay + + + + + Mamona is an embedded Linux distribution, based on + Open Embedded, for ARM EABI. + + + + + + + + + + + + + + + http://gitorious.org/projects/tante_overlay/repos/mainline + + + + + Overlay of tante + + + + + + + + + + + + + + + http://svn.netdomination.org/gentoo-voip + + + + + Voice over IP related ebuilds. + + + + + + + + + + + + + + + http://nouveau.freedesktop.org/ + + + + + Experimental ebuilds for the free nouveau driver + for nvidia cards. + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/anant/wiki + + + + + A collection of ebuilds related to the D + programming language. + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/finnish + + + + + Finnish overlay for spell checking etc. + etc. + + + + + + + + + + + + + + + http://www.gentoo.org/proj/en/desktop/lxde/ + + + + + Repo for development of ebuilds for the LXDE + desktop environment. + + + + + + + + + + + + + + + http://repo.or.cz/w/gentoo-lisp-overlay.git + + + + + Common Lisp/Scheme development, recruitment and + live overlay. Support and feedback in `#gentoo-lisp' and via + `gentoo-lisp@gentoo.org'. + + + + + + + + + + + + + + + http://git.goodpoint.de/?p=overlay-sping.git;a=summary + + + + + Gentoo overlay of Sebastian Pipping + + + + + + + + + + + + + + + http://repo.or.cz/w/gentoo-overlay-ibormuth.git + + + + + Personal Overlay of Ingo Bormuth + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/chtekk + + + + + Development overlay for a SysCP (syscp.org) ebuild + and Gentoo port, as well as additional + patches/features. + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/matsuu/ + + + + + Matsuu's Second Life Overlay + + + + + + + + + + + + + + + http://gentoo.xwing.info + + + + + This overlay contains some experimental stuff, + such as turboprint printers driver (bug #61311), intel-536ep + driver for lastest 2.6 kernels (bug #127464), lastest grisbi + version (proxy maintainer) before it's portage integration and + so on. + + + + + + + + + + + + + + + http://wiki.cregion.ru/moin.cgi/CRG_Overlay + + + + + CRG-Overlay for Gentoo Linux + + + + + + + + + + + + + Gentoo ebuild overlay with misc stuff that I find + interesting. + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/alexxy.git + + + + + Some random work in progress stuff from + alexxy + + + + + + + + + + + + + Experimental overlay for .NET + packages. + + + + + + + + + + + + + + + http://www.gentoo.org/proj/en/desktop/x/x11/ + + + + + Gentoo X11 team overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/jokey + + + + + Jokey's Overlay - Contains pre-tree stuff like + italc, pkgcore-test-ebuilds and lcd stuff + + + + + + + + + + + + + + + http://dev.gentoo.org/~falco/ + + + + + Falco's random stuff about netmon, net-mail or + security, unofficial ebuilds like proxsmtp, unofficial patches + on Postfix; also pre-stable security upgrades, perhaps merged + in the Security Overlay Project some day. + + + + + + + + + + http://sabayonlinux.org + + + Purpose To provide ebuilds that were created from + the Sabayon Linux project such as customized programs, ebuilds + not in the official portage, artwork, themes, etc. Bugs to + http://bugs.sabayonlinux.org/bugs/ + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/java + + + + + The only java overlay available via layman. This + overlays contains ebuilds that are expected to work when you + emerge them. The ebuilds also need to use the generation 2 + eclasses. + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/dirtyepic + + + + + Various work-in-progress stuff including GCC-svn + and wxGTK. + + + + + + + + + + + + + + + http://genkdesvn.mailstation.de + + + + + Paludis-only kde4 overlay. Unsupported by KDE team. + + + + + + + + + + http://overlays.gentoo.org/dev/aross + + + Personal scratch space. + + + + + + + + + + + + + + https://overlays.gentoo.org/dev/betelgeuse + + + + + Betelgeuse's developer overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/python/wiki + + + + + Python development tree, staging area for the tree. + + + + + + + + + + + + + + + http://www.hboeck.de + + + + + Purpose To provide new Xgl and AIGLX desktop + developments as mentioned on his blog. + + + + + + + + + + + + + + + http://scm.calivia.com/svn/sipx/gentoo + + + + + This repository contains sipx and related + ebuilds. + + + + + + + + + + + + + + + http://bugs.gentoo.org/show_bug.cgi?id=122500 + + + + + Testing ground for vmware-server and + vmware-server-console ebuilds until they can eventually be + committed into portage. + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/halcy0n.git;a=summary + + + + + Various packages, probably some toolchain stuff + though + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/je_fro + + + + + Helpful ebuilds for the macbook pro, and + experimental gentoo-science packages. + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/cell + + + + + Support for Cell architecture, including IBM blade + and Sony Playstation 3 + + + + + + + + + + http://overlays.gentoo.org/proj/vdr + + + Development overlay for VDR, experimental branch. + WARNING: This branch can kill your VDR! Only use it if you know + what you are doing. It is best to stay in touch with the + developers if you would like to try this out. We are available + in #gentoo-vdr on Freenode. + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/pchrist.git + + + + + Panagiotis Christopoulos developer overlay + + + + + + + + + + + + + + + http://www.gentoo.org/proj/en/kolab/index.xml + + + + + Project to allow running Kolab on + Gentoo. + + + + + + + + + + + + + + + http://www.verlihub-project.org + + + + + Verlihub is a Direct Connect protocol server runs + on Linux OS written in C++; Many features are available: MySQL + database, very low use of CPU, RAM and Bandwidth, deflood + integrated protection, plugins + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=proj/gentoo-bsd.git + + + + + Gentoo/BSD Project Overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/vdr + + + + + Overlay for VDR, that contains ebuilds for + development version of VDR, and specific plugins for that + version. + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/nirbheek.git + + + + + Nirbheek Chauhan developer overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/powerpc + + + + + Support for PowerPC-based ebuilds that are not + appropriate for the portage tree. + + + + + + + + + + + + + + + http://moving-innovations.com/blog/ + + + + + Developer overlay of Hans de Graaff with mostly + ruby and xemacs ebuilds, and a few assorted other + goodies. + + + + + + + + + + + + + + + http://gentoo-taiwan.googlecode.com/ + + + + + A collection of ebuilds from Gentoo + Taiwan. + + + + + + + + + + http://overlays.gentoo.org/dev/genstef + + + Genstef's Overlay - It usually contains some + experimental ebuilds on their way to the tree + + + + + + + + + + + + + + http://www.wolf31o2.org + + + + + Wolf31o2's project ebuilds + + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/java/wiki/GCJ_as_a_JDK + + + + + An overlay for GCJ to use as a Java SDK / + RE. + + + + + + + + + + + + + + + + http://github.com/eatnumber1/pcsx2-overlay/tree/master + + + + + Experimental overlay for pcsx2 + ebuilds. + + + + + + + + + + http://overlays.gentoo.org + + + A collection of stable ebuilds from Wolfram + Schlich [wschlich@gentoo.org]. + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/toolchain/wiki + + + + + Toolchain ebuilds that are unsuitable for the + tree. Snapshots, unstable versions, etc... + + + + + + + + + + + + + experimental gnome ebuilds + + + + + + + + + + + + + + + + http://repo.or.cz/w/dottout.git + + + + + + Dottout overlay + + + + + + + + + + + + + + + https://overlays.gentoo.org/dev/mescalinum + + + + + Tcl/Tk 8.8, Itcl/Itk 4 (beta) and other fixed packages + + + + + + + + + + + + + + + + http://code.google.com/p/gentoo-china-overlay + + + + + Purpose To provide some programs useful to Chinese + users. + + + + + + + + + + + + + + + http://opensvn.csie.org/rmh3093/iwlwifi + + + + + This overlay provides ebuilds for the new wireless + driver iwlwifi + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/matsuu.git + + + + + MATSUU Takuto developer overlay + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/jmbsvicetto.git + + + + + Jorge Manuel B. S. Vicetto developer overlay + + + + + + + + + + + + + + + http://games.gentoo.org/ + + + + + A collection of work-in-progress ebuilds and + ebuilds which require testing. + + + + + + + + + + + + + + + http://blog.pioto.org + + + + + Most things in here are still works in progress or + not stable enough for the main ebuild tree. If something + breaks, you're on your own. + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/ikelos.git;a=summary + + + + + Ikelos's hospice for broken and damaged + ebuilds. + + + + + + + + + + + + + + + http://pda.gentoo.ru + + + + + This overlay contains some pda-related ebuilds + (for now for devices such as iPAQ hx4700, Sharp Zaurus, Asus + a620 and some others) + + + + + + + + + + + + + + + http://svn.liveforge.org/berkano/trunk + + + + + Berkano overlay provides an overlay for Gentoo + Linux with ebuilds of bleeding edge software (such as live + subversion builds) and other handy tools that are missing from + the official portage tree. Areas of interest include multimedia + and system administration. + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/dagger.git;a=summary + + + + + Dagger developer overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/dev/marineam + + + + + Experimental ebuilds for Xen. + + + + + + + + + + + + + + + http://git.xnull.de/gitweb/?p=overlay.git + + + + + A collection of work-in-progress ebuilds and other + fun broken things. + + + + + + + + + + + + + + + http://armagetronad.net + + + + + 3D light cycles, like the movie TRON + + + + + + + + + + + + + + + http://blog.flameeyes.eu/ + + + + + Flameeyes' private developer overlay + + + + + + + + + + + + + + + http://www.haskell.org/~gentoo/gentoo-haskell/ + + + + + The Official Gentoo Haskell overlay. + + + + + + + + + + + + + + + http://s3d.berlios.de/ + + + + + Gentoo ebuilds for s3d and related packages. s3d + is a 3d network display server which can be used as 3d desktop + enviroment. + + + + + + + + + + + + + + + http://n4g.mars.arge.at + + + + + The goal for this overlay is to reproduce the Open + Enterprise server from novell on gentoo + + + + + + + + + + + + + Linux Terminal Server Project + overlay + + + + + + + + + + + + + + + http://n4g.mars.arge.at + + + + + The goal for this overlay is to reproduce the Open + Enterprise server from novell on gentoo + + + + + + + + + + + + + + + http://overlays.gentoo.org + + + + + Some ebuilds not yet ready for mainstream portage + from Tobias Scherbaum [dertobi123@gentoo.org]. + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/python/wiki + + + + + Python experimental tree. + + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/embedded/wiki/openmoko + + + + + Openmoko's project overlay. + + + + + + + + + + + + + experimental gpe ebuilds + + + + + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/tove.git + + + + + Torsten Veller developer overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/emacs/ + + + + + Provide Emacs related ebuilds which are a bit + experimental or work-in-progress. Don't rely on them, but don't + hesitate to file bugs or write emails. + + + + + + + + + + http://dev.gentoo.org/~hawking/ + + + hawking's random ebuilds. + + + + + + + + + + http://cafarelli.fr/websvn/listing.php?repname=voyageur-overlay + + + Voyageur's random ebuilds stuff + + + + + + + + + http://overlays.gentoo.org/proj/php + + + Development overlay for PHP, experimental + branch. + + + + + + + + + http://dev.gentoo.org/~dev-zero/ + + + Dev-zeros personal developer overlay + + + + + + + + + http://overlays.gentoo.org + + + Experimental ebuilds from the private overlay of + Ioannis Aslanidis [deathwing00@gentoo.org]. + + + + + + + + + http://overlays.gentoo.org/proj/vps + + + Gentoo VPS project overlay (experimental + ebuilds) + + + + + + + + + http://overlays.gentoo.org/proj/mozilla + + + New mozilla development that is not yet in + tree + + + + + + + + + http://www.lila-center.info + + + The Lila theme is a community project, originally + created by Daniel G. Taylor and members of the Gentoo Linux + community. The theme is based around SVG graphics - which means + they can be scaled to any size without loss of quality - and is + meant to be usable across different desktops and platforms. For + more information about the Lila theme project or to see how you + could get involved, there are a few places to look: The Lila + theme forums #lila on chat.freenode.org + + + + + + + + Temporary overlay for adding support for the EFIKA + platform to Gentoo. + + + + + + + + + http://devnull.core.ws/EbuildRepository/ + + + Various ebuilds, most of them are bleeding edge + scm versions, the others have not found their way into portage + yet. + + + + + + + + + http://overlays.gentoo.org/dev/trapni/ + + + trapni's private developer overlay (mostly + covering YaCS/server related ebuilds for now) + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/ruby/wiki + + + + + Experimental ebuilds from the Ruby + edge. + + + + + + + + + + http://overlays.gentoo.org + + + This is the home of Gentoo's wider collection of + ebuilds for web-based applications. This is where we collect + all the ebuilds submitted to Bugzilla by our users, and make + them available in an easy-to-use overlay for wider + testing. + + + + + + + + + http://www.freevo.org + + + The Freevo overlay provides ebuils for development + snapshots of the unreleased Freevo 2.0 and its + dependencies. + + + + + + + + + http://overlays.gentoo.org/proj/science/wiki/en + + + The Gentoo Science Overlay is intended as a place + to work outside of the main portage tree on experimental + ebuilds. Our aim is to increase the rate of development of + scientific packages for Gentoo, but ebuilds in this repository + are by their very nature more experimental. If you wish to use + them you should be willing to help test and report + bugs. + + + + + + + + + http://overlays.gentoo.org/dev/rbu/wiki + + + Random stuff. + + + + + + + + + http://proaudio.tuxfamily.org/wiki + + + Evermind's overlay with ebuilds for a lot of + pro-audio production software. + + + + + + + + + http://overlays.gentoo.org/dev/seemant + + + Seemant's development overlay for django and other + things. + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/remi.git + + + Remi Cardona developer overlay + + + + + + + + + + + + + + http://svn.digital-trauma.de/gentoo/ + + + + + This overlay has a binary, current version of + eclipse with many plugins and some small new ebuilds from + trauma and bugzilla.g.o. + + + + + + + + + + http://overlays.gentoo.org + + + Mostly Python-related ebuilds. + + + + + + + + + + + + + + http://dev.gentoo.org/~hwoarang/ + + + + + hwoarangs' testing ebuilds + + + + + + + + + + + + + + + http://github.com/steev/steev-overlay/tree/master + + + + + Steev Klimaszewski's Overlay + + + + + + + + + + + + + + + http://overlays.gentoo.org/proj/vdr + + + + + Overlay for VDR, that contains ebuilds for + the vdr-xine output plugin, and the needed patched xine-lib + + + + + + + + + + + + http://repo.or.cz/w/ub0rlay.git + + + + This is an ub0r overlay! + + + + + + + + + http://www.initng.org + + + Initng is a full replacement of the old and in + many ways deprecated sysvinit tool. It is designed with speed + in mind because it does as much as possible asynchronously. In + other words: It will boot your unix-system much faster, and + give you more control and statistics over your + system. + + + + + + + + + http://gentoo-wiki.com/Howto_OSS4 + + + OSSv4 overlay + + + + + + + + + http://overlays.gentoo.org/dev/anant/wiki + + + A collection of useful ebuilds related to + Plan9. + + + + + + + + + http://code.google.com/p/raw/ + + + some raw stuff + + + + + + + + + http://overlays.gentoo.org/proj/php + + + Development overlay for PHP, testing + branch. + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=proj/m68k.git + + + m68k team overlay + + + + + + + + Packages for players and authors of interactive + fiction + + + + + + + + + http://overlays.gentoo.org/dev/chtekk + + + Overlay for various applications I use myself and + plan on adding to the tree or update/fix. + + + + + + + + + http://overlays.gentoo.org/proj/postgresql + + + Development overlay for PostgreSQL, experimental + branch. + + + + + + + + + http://overlays.gentoo.org + + + Some ebuilds not yet ready for mainstream portage + from Thilo Bangert [bangert@gentoo.org]. + + + + + + + + + http://overlays.gentoo.org/dev/suka + + + experimental stuff of all sorts + + + + + + + + + http://overlays.gentoo.org/proj/vdr + + + Development overlay for VDR, testing + branch. + + + + + + + + + http://overlays.gentoo.org/proj/nx + + + Overlay for the NX/FreeNX packages for + Gentoo. + + + + + + + + + http://dev.gentoo.org/~serkan + + + Serkan Kaba's (serkan) private developer + overlay + + + + + + + + + http://github.com/gentoo-qt/qting-edge/ + + + Experimental Qt4 ebuilds and related packages, + provided by Gentoo's Qt team. The overlay contains ebuilds for + official pre-releases, and live ebuilds for both the official + Nokia Qt Software git repository and KDE's qt-copy subversion + repository. It also has various (non-KDE) packages that use + Qt4. + + + + + + + + + http://overlays.gentoo.org/proj/sunrise + + + Ebuilds for bugs assigned to + maintainer-wanted + + + + + + + + + http://overlays.gentoo.org/proj/perl/ + + + Experimental ebuilds for Perl packages in Gentoo. + Comments and bugreports are welcome! + + + + + + + + + http://overlays.gentoo.org/proj/emacs/ + + + Provide XEmacs related ebuilds which are a bit + experimental or work-in-progress. Don't rely on them, but don't + hesitate to file bugs or write emails. + + + + + + + + + http://genkdesvn.mailstation.de + + + A collection of work-in-progress ebuilds and other + fun broken things. + + + + + + + + + + + + + + https://overlays.gentoo.org/dev/mescalinum + + + + + Tcl/Tk multi-slot system, with tcltk eselect module + for switching across multiple versions (actually: 8.4 8.5 8.6) + + + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/leio.git + + + Mart Raudsepp developer overlay + + + + + + + + + http://dev.gentoo.org/~mueli + + + Overlay which provides the bleeding edge on the + kerberos integration in gentoo. + + + + + + + + + http://overlays.gentoo.org/dev/lu_zero + + + Experimental Media and PowerPC/CELL related + ebuilds. + + + + + + + + Kernel Virtual Machine userspace + support + + + + + + + + + http://overlays.gentoo.org/proj/mysql + + + Development overlay for MySQL, testing + branch. + + + + + + + + + + http://git.overlays.gentoo.org/gitweb/?p=dev/scarabeus.git + + + Tomas Chvatal developer overlay + + + + + + + + + http://overlays.gentoo.org + + + Development overlay for ebuilds that I plan to + commit to the tree that are sourced from bugzilla or + liquidx. + + + + + + + + + http://overlays.gentoo.org/proj/gcc-porting/ + + + Compatibility patches for upcoming GCC + releases. + + + + + + + + + http://luke.dashjr.org + + + Misc ebuilds by Luke-Jr + + + diff --git a/commands/parse.py b/commands/parse.py new file mode 100644 index 0000000..8fff38a --- /dev/null +++ b/commands/parse.py @@ -0,0 +1,150 @@ +from __future__ import with_statement + +import os, re + +from django.conf import settings + +os.environ['DJANGO_SETTINGS_MODULE'] = 'ebuildfnd.settings' + +from layman.debug import Message +from manage_layman import LaymanManager + +from ebuildfnd.ebuildfind.models import Ebuild, Overlay + +from whoosh_manager import WhooshEbuildManager + +OVERLAYS_BASE = "/home/timemachine/www/ebuildfnd/ebuildfind/commands/var/" +OUT = Message("parser") + +class EbuildParser: + def __init__(self, overlay, category, app, file_path): + path, filename = os.path.split(os.path.realpath(file_path)) + + #OUT.warn("%s\n%s\n%s\n%s" % (overlay, category, app, file_path)) + #OUT.warn("****************************************************") + + name_version, ext = os.path.splitext(filename) + n = len(app) + + version = name_version[n+1:] + + self.name = app + self.version = version + self.category = category + self.overlay = overlay + + with open(file_path) as file: + f = file.read() + regex1 = re.compile(r'([a-z_]+\s*\(\))\s*{.*}', re.DOTALL) + f = re.sub(regex1, r'', f) + regex2 = re.compile(r'(for.*done)', re.DOTALL) + f = re.sub(regex2, r'', f) + data = dict(re.findall("(DESCRIPTION|HOMEPAGE|KEYWORDS|LICENSE|IUSE)=\"(.+)\"", f)) + + def notnull(d, key): + try: + return d[key] + except: + return "" + + self.description = notnull(data, "DESCRIPTION") + self.description = self.description.replace("\n"," ") + self.homepage = notnull(data, "HOMEPAGE") + self.keywords = notnull(data, "KEYWORDS") + self.license = notnull(data, "LICENSE") + self.iuse = notnull(data, "IUSE") + + def __repr__(self): + output = "%s/%s [%s] @ %s" % (self.category, self.name, self.version, self.overlay) + output += " " + self.description + output += " " + self.homepage + output += " " + self.keywords + output += " " + self.license + output += " " + self.iuse + return output + +def exclude_directory(path, dir): + exclude_dir = ["eclass", "profiles", "README-TODO", "Documentation", "sets", "index"] + return os.path.isdir(path) and dir not in exclude_dir and not dir.startswith(".") + +def ParseEbuilds(): + i = 0 + Ebuild.objects.all().delete() + overlays = os.listdir(OVERLAYS_BASE) + + whoosh = WhooshEbuildManager(True) + + for overlay in overlays: + path_overlay = os.path.join(OVERLAYS_BASE, overlay) + + if exclude_directory(path_overlay, overlay): + print overlay + overlay_name = overlay + overlay = Overlay.objects.get(name=overlay) + + categories = os.listdir(path_overlay) + + for category in categories: + path_overlay_category = os.path.join(path_overlay, category) + + if exclude_directory(path_overlay_category, category): + apps = os.listdir(path_overlay_category) + for app in apps: + path_overlay_category_app = os.path.join(path_overlay_category, app) + if exclude_directory(path_overlay_category_app, app): + ebuilds = os.listdir(path_overlay_category_app) + + for ebuild in ebuilds: + if ebuild.endswith(".ebuild"): + if exclude_directory(path_overlay_category_app, ebuild): + #OUT.warn(ebuild) + + path_ebuild = os.path.join(path_overlay_category_app, ebuild) + + e = EbuildParser(overlay_name, category, app, path_ebuild) + + + ebuild = Ebuild() + ebuild.name = unicode(e.name) + ebuild.category = unicode(e.category) + ebuild.version = unicode(e.version) + ebuild.description = unicode(e.description, errors="replace") + ebuild.keywords = unicode(e.keywords) + ebuild.license = unicode(e.license) + ebuild.iuse = unicode(e.iuse) + ebuild.homepage = unicode(e.homepage) + ebuild.overlay = overlay + #ebuild.save() + + + whoosh.Update(ebuild) + + i +=1 + print i + +def SyncOverlays(): + h = LaymanManager() + h.AddAll() + +def ParseOverlays(): + h = LaymanManager() + overlays = h.List() + + for name, overlay in overlays.items() : + """ check if new overlay is ready """ + o = Overlay.objects.all().filter(name=name) + + if not o: + o = Overlay() + o.name = name + o.description = overlay["description"] + o.link = overlay["link"] + o.save() + +def main(): + #SyncOverlays() + ParseOverlays() + ParseEbuilds() + +if __name__ == "__main__": + main() diff --git a/commands/whoosh_manager.py b/commands/whoosh_manager.py new file mode 100644 index 0000000..e4acb95 --- /dev/null +++ b/commands/whoosh_manager.py @@ -0,0 +1,56 @@ +import os + +from whoosh import store +from whoosh.fields import Schema, TEXT, ID +from whoosh.index import Index +from whoosh.qparser import QueryParser + +from shutil import rmtree + +from django.conf import settings + +os.environ['DJANGO_SETTINGS_MODULE'] = 'ebuilds.settings' + +INDEX_BASE = settings.ROOT_PATH + "/ebuildfind/commands/var/index" + +class WhooshEbuildManager: + def __init__(self, reset=False): + if reset : + if os.path.exists(INDEX_BASE): + rmtree(INDEX_BASE) + os.mkdir(INDEX_BASE) + storage = store.FileStorage(INDEX_BASE) + else: + storage = store.FileStorage(INDEX_BASE) + storage = store.copy_to_ram(storage) + + schema = Schema(permalink=ID(stored=True), + content=TEXT(phrase=False)) + + self.index = Index(storage, schema=schema, create=reset) + self.searcher = self.index.searcher() + self.parser = QueryParser("content", schema = self.index.schema) + + def Update(self, ebuild): + writer = self.index.writer() + + def clean(text): + return text.lower.replace("-", " ") + + content_raw = [ebuild.overlay.name, ebuild.category, ebuild.name, ebuild.description] + content = [] + + for e in content_raw: + e = e.lower().replace("-", " ") + content.append(e) + + content.append(ebuild.version) + + content = ' '.join(content) + + writer.add_document(permalink=ebuild.permalink(), + content=content) + writer.commit() + + def Search(self, query): + return self.searcher.search(self.parser.parse(query), sortedby = "permalink") diff --git a/models.py b/models.py new file mode 100644 index 0000000..7e062d6 --- /dev/null +++ b/models.py @@ -0,0 +1,29 @@ +from django.db import models + +class Overlay(models.Model): + name = models.CharField(max_length=255) + description = models.TextField() + link = models.URLField() + + def __repr__(self): + return self.name + + def get_absolute_url(self): + return "/search/?q=%s" % self.name + +class Ebuild(models.Model): + name = models.CharField(max_length=255) + category = models.CharField(max_length=255) + version = models.CharField(max_length=255) + description = models.TextField() + keywords = models.CharField(max_length=255) + license = models.CharField(max_length=255) + iuse = models.CharField(max_length=255) + homepage = models.URLField() + overlay = models.ForeignKey(Overlay) + + def permalink(self): + return "/%s/%s/%s/%s" % (self.overlay.name, self.category, self.name, self.version) + + def get_absolute_url(self): + return "/search/?q=%s" % self.name \ No newline at end of file diff --git a/planet.py b/planet.py new file mode 100644 index 0000000..6c9abd5 --- /dev/null +++ b/planet.py @@ -0,0 +1,99 @@ +import shelve + +from feedcache.cache import Cache + +import pdb + +from django.template.defaultfilters import truncatewords_html +from django.utils.encoding import smart_unicode + +def TryEncoding(content): + for body_charset in 'UTF-8', 'US-ASCII', 'ISO-8859-1', : + try: + return content.encode(body_charset) + except UnicodeError: + pass + except Exception, e: + if not type(content) is str: + pass + + +def GetContent(feed): + if hasattr(feed, "content"): + return feed.content[0]["value"] + else: + return feed.summary + + +class Parser: + """ + "http://planet.gentoo.org/atom.xml" + "http://overlays.gentoo.org/rss20.xml" + "http://www.gentoo.org/rdf/en/gentoo-news.rdf" + >>> f = Parser() + >>> f.GetTitle() + u'Planet Gentoo' + >>> f.GetLink() + u'http://planet.gentoo.org/' + >>> for e in f: print e["title"], e["content"] + """ + + def __init__(self, url, summary=False): + storage = shelve.open(".feedcache") + try : + fc = Cache(storage) + self.feed = fc.fetch(url) + self.iterator = 0 + self.summary = summary + finally: + storage.close() + def GetTitle(self): + return self.feed.feed.title + + def GetLink(self): + return self.feed.feed.link + + def next(self): + if self.iterator >= len(self.feed.entries): raise StopIteration + + entry = self.feed.entries[self.iterator] + + title = TryEncoding(entry["title"]) + content = TryEncoding(GetContent(entry)) + link = entry.link + + if self.summary: + content = TryEncoding(truncatewords_html(content, 30)) + content = "".join((content , "...")) + + entry = dict((("title", title), ("content", content), ("link", link))) + + self.iterator += 1 + return entry + + def __iter__(self): + return self + +def _test(): + """ + import doctest, ebuilds.ebuildfind.planet as planet + return doctest.testmod(planet) + + "http://news.google.fr/news?pz=1&ned=us&hl=en&q=gentoo+AND+(linux+OR+OS+OR+Operating+System+OR+GNU)&output=rss" + "http://www.gentoo.org/rdf/en/gentoo-news.rdf" + "http://planet.gentoo.org/atom.xml" + "http://overlays.gentoo.org/rss20.xml" + """ + + f = Parser("http://planet.gentoo.org/atom.xml", True) + + print f.GetTitle() + print f.GetLink() + + for e in f: + print e["title"] + print e["content"] + print e["link"] + +if __name__ == "__main__": + _test() diff --git a/templates/ebuildfind/bakup.html b/templates/ebuildfind/bakup.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/ebuildfind/base.html b/templates/ebuildfind/base.html new file mode 100644 index 0000000..a332a1d --- /dev/null +++ b/templates/ebuildfind/base.html @@ -0,0 +1,131 @@ + + + + + ebuildfind - search engine for gentoo overlays + + + + + + + + + + +
+
+ + + +
+ + + +
+ {% block results %}{% endblock %} +
+
+ + +
+ {% block info %} +
+

Overlays Planet

+
+ + {% for post in GOverlays %} +
+
{{ post.title }}
+
{{ post.content|safe }}
+
+ {% endfor %} + +
+
+
+
+
+

Gentoo Planet

+
+ + {% for post in GPlanet %} +
+
{{ post.title }}
+
{{ post.content|truncatewords_html:100|safe }}
+
+ {% endfor %} + +
+
+
+
+ +
+

Gentoo News

+
+ + {% for post in GNews %} +
+
{{ post.title }}
+
{{ post.content|safe }}
+
+ {% endfor %} + +
+
+ +
+
+
+

Google News

+
+ + {% for post in GGoogle %} +
+
{{ post.title }}
+
{{ post.content|safe }}
+
+ {% endfor %} + +
+
+ {% endblock %} +
+
+
+

"Gentoo" and "G" logo are the property of Gentoo + Foundation, Inc.

+

This website is made + with + django and whoosh + hosted by alwaysdata.com

+
+
+ + + + diff --git a/templates/ebuildfind/index.html b/templates/ebuildfind/index.html new file mode 100755 index 0000000..7e2c510 --- /dev/null +++ b/templates/ebuildfind/index.html @@ -0,0 +1,2 @@ +{% extends "ebuildfind/base.html" %} + diff --git a/templates/ebuildfind/search.html b/templates/ebuildfind/search.html new file mode 100644 index 0000000..ced17d8 --- /dev/null +++ b/templates/ebuildfind/search.html @@ -0,0 +1,21 @@ +{% extends "ebuildfind/base.html" %} + +{% block search-value%}{{query}}{% endblock %} + +{% block help %}{% endblock %} + +{% block results %} + +{% if error %} +

{{search_results.error}}

+{% endif %} + +
    + {% for result in results %} +
  • {{result}}
  • + {% endfor %} +
+ +{% endblock %} + +{% block info %}{% endblock %} diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..41d3376 --- /dev/null +++ b/urls.py @@ -0,0 +1,15 @@ +from django.conf.urls.defaults import * +import views + +urlpatterns = patterns('', + # Example: + + + # Uncomment the admin/doc line below and add 'django.contrib.admindocs' + # to INSTALLED_APPS to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + (r'^search/', views.search), + (r'^$', views.index), +) diff --git a/views.py b/views.py new file mode 100644 index 0000000..cc17e83 --- /dev/null +++ b/views.py @@ -0,0 +1,48 @@ + + + + + +from commands.whoosh_manager import WhooshEbuildManager +from django.shortcuts import render_to_response +from planet import Parser + +whoosh = WhooshEbuildManager() + + +def index(request): + GPlanet = Parser("http://planet.gentoo.org/atom.xml") + GOverlays = Parser("http://overlays.gentoo.org/rss20.xml") + GNews = Parser("http://www.gentoo.org/rdf/en/gentoo-news.rdf") + GGoogle = Parser("http://news.google.fr/news?pz=1&ned=us&hl=en&q=gentoo+AND+(linux+OR+OS+OR+Operating+System+OR+GNU)&output=rss") + + response = dict() + response['GGoogle'] = GGoogle + response['GNews'] = GNews + response['GOverlays'] = GOverlays + response['GPlanet'] = GPlanet + + return render_to_response("ebuildfind/index.html", response) + + +def search(request): + response = {"error":"Query should be at least 3 caracters long"} + query = "" + + if request.method == 'GET': + try: + query = request.GET["q"] + except: + pass + + if(len(query)>2): + response["error"] = False + response["query"] = query + + results = whoosh.Search(query) + response["results"] = list() + + for result in results: + response["results"].append(result["permalink"]) + + return render_to_response("ebuildfind/search.html", response) -- 2.11.4.GIT From a6630aeb7290c240d9529dbc2f29d51edda70709 Mon Sep 17 00:00:00 2001 From: abki Date: Wed, 1 Jul 2009 14:46:48 +0200 Subject: [PATCH 2/6] static files --- static/css/960.css | 491 ++++++++++++++++++++++++++++++++++++++++++++ static/css/grid.css | 491 ++++++++++++++++++++++++++++++++++++++++++++ static/css/ie.css | 31 +++ static/css/ie6.css | 31 +++ static/css/layout.css | 86 ++++++++ static/css/nav.css | 171 +++++++++++++++ static/css/reset.css | 53 +++++ static/css/text.css | 98 +++++++++ static/img/ajax-loader.gif | Bin 0 -> 1849 bytes static/img/glogo-small.png | Bin 0 -> 3878 bytes static/img/photo_60x60.jpg | Bin 0 -> 514 bytes static/img/photo_60x60.psd | Bin 0 -> 44528 bytes static/img/switch_minus.gif | Bin 0 -> 119 bytes static/img/switch_plus.gif | Bin 0 -> 124 bytes 14 files changed, 1452 insertions(+) create mode 100755 static/css/960.css create mode 100755 static/css/grid.css create mode 100755 static/css/ie.css create mode 100755 static/css/ie6.css create mode 100755 static/css/layout.css create mode 100755 static/css/nav.css create mode 100755 static/css/reset.css create mode 100755 static/css/text.css create mode 100755 static/img/ajax-loader.gif create mode 100644 static/img/glogo-small.png create mode 100755 static/img/photo_60x60.jpg create mode 100755 static/img/photo_60x60.psd create mode 100755 static/img/switch_minus.gif create mode 100755 static/img/switch_plus.gif diff --git a/static/css/960.css b/static/css/960.css new file mode 100755 index 0000000..6db1bd3 --- /dev/null +++ b/static/css/960.css @@ -0,0 +1,491 @@ +/* + 960 Grid System ~ Core CSS. + Learn more ~ http://960.gs/ + + Licensed under GPL and MIT. +*/ + +/* =Containers +--------------------------------------------------------------------------------*/ + +.container_12, +.container_16 +{ + margin-left: auto; + margin-right: auto; + width: 960px; +} + +/* =Grid >> Global +--------------------------------------------------------------------------------*/ + +.grid_1, +.grid_2, +.grid_3, +.grid_4, +.grid_5, +.grid_6, +.grid_7, +.grid_8, +.grid_9, +.grid_10, +.grid_11, +.grid_12, +.grid_13, +.grid_14, +.grid_15, +.grid_16 +{ + display: inline; + float: left; + margin-left: 10px; + margin-right: 10px; +} + +.container_12 .grid_3, +.container_16 .grid_4 +{ + width: 220px; +} + +.container_12 .grid_6, +.container_16 .grid_8 +{ + width: 460px; +} + +.container_12 .grid_9, +.container_16 .grid_12 +{ + width: 700px; +} + +.container_12 .grid_12, +.container_16 .grid_16 +{ + width: 940px; +} + +/* =Grid >> Children (Alpha ~ First, Omega ~ Last) +--------------------------------------------------------------------------------*/ + +.alpha +{ + margin-left: 0; +} + +.omega +{ + margin-right: 0; +} + +/* =Grid >> 12 Columns +--------------------------------------------------------------------------------*/ + +.container_12 .grid_1 +{ + width: 60px; +} + +.container_12 .grid_2 +{ + width: 140px; +} + +.container_12 .grid_4 +{ + width: 300px; +} + +.container_12 .grid_5 +{ + width: 380px; +} + +.container_12 .grid_7 +{ + width: 540px; +} + +.container_12 .grid_8 +{ + width: 620px; +} + +.container_12 .grid_10 +{ + width: 780px; +} + +.container_12 .grid_11 +{ + width: 860px; +} + +/* =Grid >> 16 Columns +--------------------------------------------------------------------------------*/ + +.container_16 .grid_1 +{ + width: 40px; +} + +.container_16 .grid_2 +{ + width: 100px; +} + +.container_16 .grid_3 +{ + width: 160px; +} + +.container_16 .grid_5 +{ + width: 280px; +} + +.container_16 .grid_6 +{ + width: 340px; +} + +.container_16 .grid_7 +{ + width: 400px; +} + +.container_16 .grid_9 +{ + width: 520px; +} + +.container_16 .grid_10 +{ + width: 580px; +} + +.container_16 .grid_11 +{ + width: 640px; +} + +.container_16 .grid_13 +{ + width: 760px; +} + +.container_16 .grid_14 +{ + width: 820px; +} + +.container_16 .grid_15 +{ + width: 880px; +} + +/* =Prefix Extra Space >> Global +--------------------------------------------------------------------------------*/ + +.container_12 .prefix_3, +.container_16 .prefix_4 +{ + padding-left: 240px; +} + +.container_12 .prefix_6, +.container_16 .prefix_8 +{ + padding-left: 480px; +} + +.container_12 .prefix_9, +.container_16 .prefix_12 +{ + padding-left: 720px; +} + +/* =Prefix Extra Space >> 12 Columns +--------------------------------------------------------------------------------*/ + +.container_12 .prefix_1 +{ + padding-left: 80px; +} + +.container_12 .prefix_2 +{ + padding-left: 160px; +} + +.container_12 .prefix_4 +{ + padding-left: 320px; +} + +.container_12 .prefix_5 +{ + padding-left: 400px; +} + +.container_12 .prefix_7 +{ + padding-left: 560px; +} + +.container_12 .prefix_8 +{ + padding-left: 640px; +} + +.container_12 .prefix_10 +{ + padding-left: 800px; +} + +.container_12 .prefix_11 +{ + padding-left: 880px; +} + +/* =Prefix Extra Space >> 16 Columns +--------------------------------------------------------------------------------*/ + +.container_16 .prefix_1 +{ + padding-left: 60px; +} + +.container_16 .prefix_2 +{ + padding-left: 120px; +} + +.container_16 .prefix_3 +{ + padding-left: 180px; +} + +.container_16 .prefix_5 +{ + padding-left: 300px; +} + +.container_16 .prefix_6 +{ + padding-left: 360px; +} + +.container_16 .prefix_7 +{ + padding-left: 420px; +} + +.container_16 .prefix_9 +{ + padding-left: 540px; +} + +.container_16 .prefix_10 +{ + padding-left: 600px; +} + +.container_16 .prefix_11 +{ + padding-left: 660px; +} + +.container_16 .prefix_13 +{ + padding-left: 780px; +} + +.container_16 .prefix_14 +{ + padding-left: 840px; +} + +.container_16 .prefix_15 +{ + padding-left: 900px; +} + +/* =Suffix Extra Space >> Global +--------------------------------------------------------------------------------*/ + +.container_12 .suffix_3, +.container_16 .suffix_4 +{ + padding-right: 240px; +} + +.container_12 .suffix_6, +.container_16 .suffix_8 +{ + padding-right: 480px; +} + +.container_12 .suffix_9, +.container_16 .suffix_12 +{ + padding-right: 720px; +} + +/* =Suffix Extra Space >> 12 Columns +--------------------------------------------------------------------------------*/ + +.container_12 .suffix_1 +{ + padding-right: 80px; +} + +.container_12 .suffix_2 +{ + padding-right: 160px; +} + +.container_12 .suffix_4 +{ + padding-right: 320px; +} + +.container_12 .suffix_5 +{ + padding-right: 400px; +} + +.container_12 .suffix_7 +{ + padding-right: 560px; +} + +.container_12 .suffix_8 +{ + padding-right: 640px; +} + +.container_12 .suffix_10 +{ + padding-right: 800px; +} + +.container_12 .suffix_11 +{ + padding-right: 880px; +} + +/* =Suffix Extra Space >> 16 Columns +--------------------------------------------------------------------------------*/ + +.container_16 .suffix_1 +{ + padding-right: 60px; +} + +.container_16 .suffix_2 +{ + padding-right: 120px; +} + +.container_16 .suffix_3 +{ + padding-right: 180px; +} + +.container_16 .suffix_5 +{ + padding-right: 300px; +} + +.container_16 .suffix_6 +{ + padding-right: 360px; +} + +.container_16 .suffix_7 +{ + padding-right: 420px; +} + +.container_16 .suffix_9 +{ + padding-right: 540px; +} + +.container_16 .suffix_10 +{ + padding-right: 600px; +} + +.container_16 .suffix_11 +{ + padding-right: 660px; +} + +.container_16 .suffix_13 +{ + padding-right: 780px; +} + +.container_16 .suffix_14 +{ + padding-right: 840px; +} + +.container_16 .suffix_15 +{ + padding-right: 900px; +} + +/* =Clear Floated Elements +--------------------------------------------------------------------------------*/ + +/* http://sonspring.com/journal/clearing-floats */ + +html body * span.clear, +html body * div.clear, +html body * li.clear, +html body * dd.clear +{ + background: none; + border: 0; + clear: both; + display: block; + float: none; + font-size: 0; + list-style: none; + margin: 0; + padding: 0; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; +} + +/* http://www.positioniseverything.net/easyclearing.html */ + +.clearfix:after +{ + clear: both; + content: '.'; + display: block; + visibility: hidden; + height: 0; +} + +.clearfix +{ + display: inline-block; +} + +* html .clearfix +{ + height: 1%; +} + +.clearfix +{ + display: block; +} \ No newline at end of file diff --git a/static/css/grid.css b/static/css/grid.css new file mode 100755 index 0000000..dd21d4e --- /dev/null +++ b/static/css/grid.css @@ -0,0 +1,491 @@ +/* + 960 Grid System ~ Core CSS. + Learn more ~ http://960.gs/ + + Licensed under GPL and MIT. +*/ + +/* =Containers +--------------------------------------------------------------------------------*/ + +.container_12, +.container_16 +{ + width: 92%; + margin-left: 4%; + margin-right: 4%; +} + +/* =Grid >> Global +--------------------------------------------------------------------------------*/ + +.grid_1, +.grid_2, +.grid_3, +.grid_4, +.grid_5, +.grid_6, +.grid_7, +.grid_8, +.grid_9, +.grid_10, +.grid_11, +.grid_12, +.grid_13, +.grid_14, +.grid_15, +.grid_16 +{ + display: inline; + float: left; + margin-left: 1%; + margin-right: 1%; +} + +.container_12 .grid_3, +.container_16 .grid_4 +{ + width: 23%; +} + +.container_12 .grid_6, +.container_16 .grid_8 +{ + width: 48%; +} + +.container_12 .grid_9, +.container_16 .grid_12 +{ + width: 73%; +} + +.container_12 .grid_12, +.container_16 .grid_16 +{ + width: 98%; +} + +/* =Grid >> Children (Alpha ~ First, Omega ~ Last) +--------------------------------------------------------------------------------*/ + +.alpha +{ + margin-left: 0; +} + +.omega +{ + margin-right: 0; +} + +/* =Grid >> 12 Columns +--------------------------------------------------------------------------------*/ + +.container_12 .grid_1 +{ + width: 6.333%; +} + +.container_12 .grid_2 +{ + width: 14.666%; +} + +.container_12 .grid_4 +{ + width: 31.333%; +} + +.container_12 .grid_5 +{ + width: 39.666%; +} + +.container_12 .grid_7 +{ + width: 56.333%; +} + +.container_12 .grid_8 +{ + width: 64.666%; +} + +.container_12 .grid_10 +{ + width: 81.333%; +} + +.container_12 .grid_11 +{ + width: 89.666%; +} + +/* =Grid >> 16 Columns +--------------------------------------------------------------------------------*/ + +.container_16 .grid_1 +{ + width: 4.25%; +} + +.container_16 .grid_2 +{ + width: 10.5%; +} + +.container_16 .grid_3 +{ + width: 16.75%; +} + +.container_16 .grid_5 +{ + width: 29.25%; +} + +.container_16 .grid_6 +{ + width: 35.5%; +} + +.container_16 .grid_7 +{ + width: 41.75%; +} + +.container_16 .grid_9 +{ + width: 54.25%; +} + +.container_16 .grid_10 +{ + width: 60.5%; +} + +.container_16 .grid_11 +{ + width: 66.75%; +} + +.container_16 .grid_13 +{ + width: 79.25%; +} + +.container_16 .grid_14 +{ + width: 85.5%; +} + +.container_16 .grid_15 +{ + width: 91.75%; +} + +/* =Prefix Extra Space >> Global +--------------------------------------------------------------------------------*/ + +.container_12 .prefix_3, +.container_16 .prefix_4 +{ + padding-left: 25%; +} + +.container_12 .prefix_6, +.container_16 .prefix_8 +{ + padding-left: 50%; +} + +.container_12 .prefix_9, +.container_16 .prefix_12 +{ + padding-left: 75%; +} + +/* =Prefix Extra Space >> 12 Columns +--------------------------------------------------------------------------------*/ + +.container_12 .prefix_1 +{ + padding-left: 8.333%; +} + +.container_12 .prefix_2 +{ + padding-left: 16.666%; +} + +.container_12 .prefix_4 +{ + padding-left: 33.333%; +} + +.container_12 .prefix_5 +{ + padding-left: 41.666%; +} + +.container_12 .prefix_7 +{ + padding-left: 58.333%; +} + +.container_12 .prefix_8 +{ + padding-left: 66.666%; +} + +.container_12 .prefix_10 +{ + padding-left: 83.333%; +} + +.container_12 .prefix_11 +{ + padding-left: 91.666%; +} + +/* =Prefix Extra Space >> 16 Columns +--------------------------------------------------------------------------------*/ + +.container_16 .prefix_1 +{ + padding-left: 6.25%; +} + +.container_16 .prefix_2 +{ + padding-left: 12.5%; +} + +.container_16 .prefix_3 +{ + padding-left: 18.75%; +} + +.container_16 .prefix_5 +{ + padding-left: 31.25%; +} + +.container_16 .prefix_6 +{ + padding-left: 37.5%; +} + +.container_16 .prefix_7 +{ + padding-left: 43.75%; +} + +.container_16 .prefix_9 +{ + padding-left: 56.25%; +} + +.container_16 .prefix_10 +{ + padding-left: 62.5%; +} + +.container_16 .prefix_11 +{ + padding-left: 68.75%; +} + +.container_16 .prefix_13 +{ + padding-left: 81.25%; +} + +.container_16 .prefix_14 +{ + padding-left: 87.5%; +} + +.container_16 .prefix_15 +{ + padding-left: 93.75%; +} + +/* =Suffix Extra Space >> Global +--------------------------------------------------------------------------------*/ + +.container_12 .suffix_3, +.container_16 .suffix_4 +{ + padding-right: 25%; +} + +.container_12 .suffix_6, +.container_16 .suffix_8 +{ + padding-right: 50%; +} + +.container_12 .suffix_9, +.container_16 .suffix_12 +{ + padding-right: 75%; +} + +/* =Suffix Extra Space >> 12 Columns +--------------------------------------------------------------------------------*/ + +.container_12 .suffix_1 +{ + padding-right: 8.333%; +} + +.container_12 .suffix_2 +{ + padding-right: 16.666%; +} + +.container_12 .suffix_4 +{ + padding-right: 33.333%; +} + +.container_12 .suffix_5 +{ + padding-right: 41.666%; +} + +.container_12 .suffix_7 +{ + padding-right: 58.333%; +} + +.container_12 .suffix_8 +{ + padding-right: 66.666%; +} + +.container_12 .suffix_10 +{ + padding-right: 83.333%; +} + +.container_12 .suffix_11 +{ + padding-right: 91.666%; +} + +/* =Suffix Extra Space >> 16 Columns +--------------------------------------------------------------------------------*/ + +.container_16 .suffix_1 +{ + padding-right: 6.25%; +} + +.container_16 .suffix_2 +{ + padding-right: 16.5%; +} + +.container_16 .suffix_3 +{ + padding-right: 18.75%; +} + +.container_16 .suffix_5 +{ + padding-right: 31.25%; +} + +.container_16 .suffix_6 +{ + padding-right: 37.5%; +} + +.container_16 .suffix_7 +{ + padding-right: 43.75%; +} + +.container_16 .suffix_9 +{ + padding-right: 56.25%; +} + +.container_16 .suffix_10 +{ + padding-right: 62.5%; +} + +.container_16 .suffix_11 +{ + padding-right: 68.75%; +} + +.container_16 .suffix_13 +{ + padding-right: 81.25%; +} + +.container_16 .suffix_14 +{ + padding-right: 87.5%; +} + +.container_16 .suffix_15 +{ + padding-right: 93.75%; +} + +/* =Clear Floated Elements +--------------------------------------------------------------------------------*/ + +/* http://sonspring.com/journal/clearing-floats */ + +html body * span.clear, +html body * div.clear, +html body * li.clear, +html body * dd.clear +{ + background: none; + border: 0; + clear: both; + display: block; + float: none; + font-size: 0; + list-style: none; + margin: 0; + padding: 0; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; +} + +/* http://www.positioniseverything.net/easyclearing.html */ + +.clearfix:after +{ + clear: both; + content: '.'; + display: block; + visibility: hidden; + height: 0; +} + +.clearfix +{ + display: inline-block; +} + +* html .clearfix +{ + height: 1%; +} + +.clearfix +{ + display: block; +} \ No newline at end of file diff --git a/static/css/ie.css b/static/css/ie.css new file mode 100755 index 0000000..7fe61ff --- /dev/null +++ b/static/css/ie.css @@ -0,0 +1,31 @@ +/* + Fluid 960 Grid System - IE Fixes (IE7 and greater) + Learn more ~ http://www.designinfluences.com/ + + Licensed under GPL and MIT. +*/ + +/* =Grid >> Global +--------------------------------------------------------------------------------*/ + +.grid_1, +.grid_2, +.grid_3, +.grid_4, +.grid_5, +.grid_6, +.grid_7, +.grid_8, +.grid_9, +.grid_10, +.grid_11, +.grid_12, +.grid_13, +.grid_14, +.grid_15, +.grid_16 +{ + margin-left: .92%; + margin-right: .92%; +} + diff --git a/static/css/ie6.css b/static/css/ie6.css new file mode 100755 index 0000000..b1ff5b5 --- /dev/null +++ b/static/css/ie6.css @@ -0,0 +1,31 @@ +/* + Fluid 960 Grid System - IE6 Fixes + Learn more ~ http://www.designinfluences.com/ + + Licensed under GPL and MIT. +*/ + +/* =Grid >> Global +--------------------------------------------------------------------------------*/ + +.grid_1, +.grid_2, +.grid_3, +.grid_4, +.grid_5, +.grid_6, +.grid_7, +.grid_8, +.grid_9, +.grid_10, +.grid_11, +.grid_12, +.grid_13, +.grid_14, +.grid_15, +.grid_16 +{ + margin-left: .8%; + margin-right: .8%; +} + diff --git a/static/css/layout.css b/static/css/layout.css new file mode 100755 index 0000000..61def42 --- /dev/null +++ b/static/css/layout.css @@ -0,0 +1,86 @@ +/* +----------------------------------------------- +Grey Box Method - Layout CSS +----------------------------------------------- */ + +body { + background: #FFF; + color: #333; + font-size: 11px; + padding: 50px 0 40px; +} + +h7 { font-size: 11px; font-weight: normal;} + +.post { overflow : hidden; } +/* anchors +----------------------------------------------- */ + +/* 960 grid system container background +----------------------------------------------- */ + +/* headings +----------------------------------------------- */ + +/* search-box +----------------------------------------------- */ + +#search-box { + text-align: center; +} + +#search-box img { + margin-bottom: 20px; +} + + +#search-box div { + margin: 10px; + margin-bottom: 40px; +} + +#results { + margin-bottom: 40px; +} + +/* bottom +----------------------------------------------- */ +#bottom { + text-align: center; +} + +/* boxes +----------------------------------------------- */ + +/* paragraphs, quotes and lists +----------------------------------------------- */ + +/* menus +----------------------------------------------- */ + +/* submenus +----------------------------------------------- */ + +/* section menus +----------------------------------------------- */ + +/* table +----------------------------------------------- */ + +/* forms +----------------------------------------------- */ + +/* articles +----------------------------------------------- */ + +/* site information +----------------------------------------------- */ + +/* AJAX sliding shelf +----------------------------------------------- */ + +/* Accordian +----------------------------------------------- */ + +/* Mootools Kwicks +----------------------------------------------- */ diff --git a/static/css/nav.css b/static/css/nav.css new file mode 100755 index 0000000..7cb8440 --- /dev/null +++ b/static/css/nav.css @@ -0,0 +1,171 @@ +/* +----------------------------------------------- +Navigation +----------------------------------------------- */ + +/* navigation (horizontal subnavigation) +----------------------------------------------- */ +ul.nav, +ul.nav * { margin:0;padding:0;} +ul.nav { + position:relative; + background:#666; + max-width:100%; + height:2.5em; + } +ul.nav li { + cursor:pointer; + float:left; + text-align:center; + list-style-type:none; + font-weight:normal; +} +ul.nav li ul { + cursor:default; + width:100%; + max-width:100%; + position:absolute; + height:auto; + top:2.5em; + background-position:0 0 !important; + left:-9000px; +} +ul.nav li ul li { + padding:0; + border:none; + width:auto; + max-width:none; +} +ul.nav li a { + color:#fff; + background:#666; + font-weight:bold; + text-decoration:none; + display:block; + float:left; + padding:0 1em; + height:2.4em; + line-height:2.5em; +} +ul.nav li ul li a { + position:relative !important; /* ie Mac */ + cursor:pointer !important; + white-space:nowrap; + line-height:2em; + height:2em; + font-weight:normal; + color:#666; + background-position:0 50% !important; +} + +ul.nav li:hover a, +ul.nav li a:hover, +ul.nav li a:focus {color:#000; background:#ccc;} +ul.nav li a:active {color:#666; background:#fff;} +ul.nav li:hover ul {left:0;z-index:10} +ul.nav li ul, +ul.nav li {background:#ccc !important} +ul.nav li:hover ul li a {color:#444;} +ul.nav li:hover ul li a:hover {color:#000; background:#fff;} +ul.nav li:hover ul li a:active {color:#666; background:#fff;} + +ul.nav li.current a {color:#666; background:#fff; cursor:default; font-weight:bold;} +ul.nav li.current ul {left:0;z-index:5} +ul.nav li.current ul, +ul.nav li.current {background:#ccc !important} +ul.nav li.current ul li a {color:#444; background:#ccc; font-weight:normal;} +ul.nav li.current ul li a:hover {color:#000; background:#fff;} +ul.nav li ul li.current a, +ul.nav li ul li.current a:hover, +ul.nav li.current:hover ul li a:active {color:#666; background:#fff;} + + +/* navigation (vertical subnavigation) +----------------------------------------------- */ +ul.nav { + background:#666; +} +ul.main li { + position:relative; + top:0; + left:0; +} +ul.main li ul { + border-top:0; +} +ul.main li ul li { + float:left; +} +ul.main li a { + height:2.5em; + line-height:2.5em; + border:0; + color:#fff; + background:#666; +} +ul.main li ul li a { + width:12em; + line-height:2em; + height:2em; + text-align:left; + color:#fff; + border-top:1px solid #444; + background:#444; +} +ul.main li a:focus {color:#fff; background:#666;} +ul.main li ul li a:hover { + color:#fff; + background:#555; +} +ul.main li:hover a { + color:#fff; + background:#555; +} +ul.main li:hover ul li a {color:#fff;} +ul.main li:hover ul li a:hover {color:#fff; background:#444;} +ul.main li:hover a:active {background:#444;} +ul.main li:hover ul li a:active {color:#fff; background:#222;} + + +/* secondary list +----------------------------------------------- */ +ul.nav li.secondary { + float:right; + color:#cde; + background:transparent !important; +} +ul.nav li.secondary span.status { + float:left; + padding:0 1em; + line-height:2.77em; + height:2.77em; + font-size:0.9em; +} +ul.nav li.secondary span.status a { + float:none; + display:inline; + padding:0; + height:auto; + line-height:auto; + color:#cde; + background:transparent; +} +ul.nav li.secondary span.status a:hover { + color:#fff; + background:transparent; +} +ul.nav li.secondary span.status span { + text-transform:capitalize; +} +ul.nav li.secondary:hover a { + color:#fff; + background:#666; +} +ul.nav li.secondary:hover a:hover { + background:#555; +} +ul.nav li.secondary:hover a:active {background:#444;} + +#results li:hover { + font-weight: bold; +} \ No newline at end of file diff --git a/static/css/reset.css b/static/css/reset.css new file mode 100755 index 0000000..3aadd3d --- /dev/null +++ b/static/css/reset.css @@ -0,0 +1,53 @@ +/* http://meyerweb.com/eric/tools/css/reset/ */ +/* v1.0 | 20080212 */ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-size: 100%; + vertical-align: baseline; + background: transparent; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +/* remember to define focus styles! */ +:focus { + outline: 0; +} + +/* remember to highlight inserts somehow! */ +ins { + text-decoration: none; +} +del { + text-decoration: line-through; +} + +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: collapse; + border-spacing: 0; +} \ No newline at end of file diff --git a/static/css/text.css b/static/css/text.css new file mode 100755 index 0000000..b6a687b --- /dev/null +++ b/static/css/text.css @@ -0,0 +1,98 @@ +/* + 960 Grid System ~ Text CSS. + Learn more ~ http://960.gs/ + + Licensed under GPL and MIT. +*/ + +/* =Basic HTML +--------------------------------------------------------------------------------*/ + +body +{ + font: 13px/1.5 Helvetica, Arial, 'Liberation Sans', FreeSans, sans-serif; +} + +a:focus +{ + outline: 1px dotted invert; +} + +hr +{ + border-color: #ccc; + border-style: solid; + border-width: 1px 0 0; + clear: both; + height: 0; +} + +/* =Headings +--------------------------------------------------------------------------------*/ + +h1 +{ + font-size: 25px; +} + +h2 +{ + font-size: 23px; +} + +h3 +{ + font-size: 21px; +} + +h4 +{ + font-size: 19px; +} + +h5 +{ + font-size: 17px; +} + +h6 +{ + font-size: 15px; +} + +/* =Spacing +--------------------------------------------------------------------------------*/ + +ol +{ + list-style: decimal; +} + +ul +{ + list-style: square; +} + +li +{ + margin-left: 30px; +} + +p, +dl, +hr, +h1, +h2, +h3, +h4, +h5, +h6, +ol, +ul, +pre, +table, +address, +fieldset +{ + margin-bottom: 20px; +} \ No newline at end of file diff --git a/static/img/ajax-loader.gif b/static/img/ajax-loader.gif new file mode 100755 index 0000000000000000000000000000000000000000..25b1f60458debdb6c505a076a895cff58ab32e91 GIT binary patch literal 1849 zcwUv$dr(t%76DNwg}n+zWM?&GHTm#SFF=c+wF{W*d1+M3Vlq~Y3q{Ctbb+N+4JX_ zb7nsCJ#*4GZ8Wa4K?EW{Ac$VCfAHWza&mHacell2xpe8$z`(##=iIq-v$M0cwYBBt z<@59NE|=^6{rlIiUmqSGM*g3Qd_ZTXZGJq(l#>>>R);MMw0@PO)Yxsc_HEL7N9}g0 zt-{t&xx=fA99Z2Loz^9g`)Pd~)62a@GQWWJ!{%Z(LHItW3JtG+rzMEJ4Cq$<% z*haC}Q{8^}Z%+Eu*-+E%C+_y-404Na%eHvjr*fnCf1fqGij$69r7y+~ix@G!;~(qe zf)MRUxYfB`F78aRMRQWTV zOp}q_)Va8T&djWZpy52C7No2V}8r! zv-l;9Hl-wHp&zSvH=IbpxGUG}M3cvfZBj0yAw&LjmVCQPz`VDQ<60o%lZ|AVOXDq<04j_ zf8@d$QK&>4d%=Ol!#2NlBLAes2Qc$jllef%*6s4j$_N6tWjnMCQ9>|EWv7N9kt}=V zZazU*Id&m{V5{s!F+oYs2S}UX63H(k|NOmSTIC;-C8k|H;B|573PslH8_wzquCV0| z-@SK3q>T65XznC{c>Re&r4)Ldm6(F+Zgt%_*+r7oKh~+1hY>{H>M|bW6IMc~R4Nz( zBc9t`YUu%O$)&{tVvQiZDv|7v2iMd;)SxQ$Ua4YQHL3X7oKPf+6)zi?zE(K?@h02$ zNM8EEVS9u4h4DKUU7P*9Vam_tH*Oih!D9ToXH%=jTcYKHtFL_H6f+dRn84E!tbxyG zcOhI1Xao#{3W>*JC?a;hhM#6jKr5BMlZ{8 z`7oMwU<4)@>P}NOy#`9ZLFi z@3qloPa0iYt?{>?9b85Ghs;|M_ty6sA|`S5*o7M*;gh{b$36<1yt;gDM!^>mS0+Xu zl>(aNMN`Qb!IC)5P;n|i2+?+wCv>Q2z81&V!~PgKhV2Zlse7oYEE<;2QsWj_UGz79 zHKXsh<`&%*BrJE`T^}xJe`x`1dLmLcRbxsuikXz1BRwC4;{VLZDR+cS&N-0WKG5wk z<#5iGFonlPry^_)4+3Fsyn(@&Fs!4@fkHC7LRZgvmBC-?VJ>T#>d7HWosQCPS|C!R zcq_uvV`RwIl!ZA}NPFuZ^J#Uzq^srY)#43Qi>u@G7vZAqV@yGl2EN~Gol*0d)&oBd viq&_LF% literal 0 HcwPel00001 diff --git a/static/img/glogo-small.png b/static/img/glogo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..47ab5b5c5b0347994586d0824c1cbafa2104c793 GIT binary patch literal 3878 zcwUuPcTm&Y*8PR9)PR6Qq$^?sZ-7vP6cGVwg7hFtHB^Dn@k+H}K;%(Hic}2&Lz5Cf zdbtD$-QWf3RZ0Q@6v#vGy!Xxf^E+qe%$Zqxud`;)nZ3@TPtd;sJcfD(dH@K-0O+4g zfIbOa2iRCxSXr3aSXo(5onkx9afXwFot;C7myi3*d5EaUd5EyEn3SBfn8X!HVc|>4 zGFSe9DJm+8N~>z9$Rp$w6y<-BfKHt{#lg;TmXq_WytuHq{QrB+c>@Jm^2DLB7ANftUGW&9sv0Q4*Q1d;-u@SGg`&+;D# zd_u~keVb3>jLv;OIvL>j6#!-g1De3z4g&~?)XoW4zJ9(W+pkIUNk6rjn>%wTz5KD5 zlR*t{?=0D7ueqCW9JA*D-(NZ^ysK{#j@XbW@Dg#zI5Hf%hIFiabp|7^w7KbW1u5U1>|3d$)$Uet$(N&m zNG&lQHl`CH(d@xu`3}PquV66)UAY$gZ%lHbw^DlD7tv?O)J`A9AMmQ>aBDR{pQO*F z>iX^s=2rwlBY!eYq-BiHST>LQ%0OZqYm$n(CmYT|#u8aD4E^#(KTuXSYOkd< zocUW~al`juVOz`MdQvyH_|LMx$Ct`CZm%>ohJ0w9$i3%$uA8|doVXNZXlW)EZKEyB zzjj~e0eZ`Uze0%8Sr2u+Gw(#Mh-2r^xXP;-oNjN`eZ%~FpYG%!VMD|lVYh&+MWw1s zpaVMG)?Cjrn#_Opdzn+5NeQ@DBeU6=q>d`({asa7dHwEu^lKG3hN(6Oh`JOsX^}ay zO2$(}jE{OZ3iKcWIkz?Q3;yV0l6`UU2|izoVYa$xxb9Xppe4qY>8EXHL#6|^%O}{$|#(TBbrvB2$FgEUp4xB3#A`R{3tbEfHeK*Oh zYV*Kr7j#olB!5a@Im@ysp3>CJ^UR|R9m@c`WhsH#XJFUIaD7Kcpnh=3GHc{Ev|?Ig z)(L-bi0wUPRTB?$3%#I}!KYm1q8%Bj5ixEmZ1dxp#ZN=KbDsX#zvOOUA!s?&w?7SQ zIueeh16U>;?XMcy7U^yK(3aW`Q5HPk1=|P+2H=*roxuh zF3S~`!3emV=F^M%5o-L4j~wNi8zEMmg-fL;^=1ow|Hb!#cl-HG&(!F)gO5bTSLWXMKx$#@d`R7c2P2^WP- z&5_j{*`rVi%tHO9q9WhlTX)@u1>zO4a+7_!Pr2?@w|rFzy&@B?i-YmHPDH%K>yFoL zNY;3whqc@N94cY2>&+$2{d(Gk{EbybWTGbvBy9cRfx3APEhyetU8olBirsnI;b`Lu z3nq&gMD$kY+Drh~?(f{S9;a?+2W}U-bk|z3F^SmHlB|sW3@b7b+nNLvQv;@ba*A@I zm)jmmIQynMRIW>Nemu`tCz$&7{1I_$m%YLhnKFW{dzyE+ZSEv>5dq1x(r7=Kst zQgwL3%!BmQ*Gu|ZVui0e#(Uc8E|J=1LKX!k0w&LFfMFFa?F(B}q06fMzHd}k)#8>P zD{*XN(M3f(E43kCs)NI$3fnfP!VLyz{1sy%ytXbJ2PQvV2^dQC*LQcrkT9+eyW~t*ac-ZD`d8s*%>vt|*&fInbJ?HwlsTam7__-uH z(8O$HQV_C``3WXC-!-2rVddvW$U;nP@>Itghktlvo1gl~8pJeNPY1Y6faAD83xw$h zW6t!(iuEjstn@@mbNu6n#+ro!m){9d;z)O7x<{)F`M-`97=i_`x_LbwHC@;G4!WHow+MiV-`#o7 zd%9Jd=`PF-2m3q!H745x*VaE?(^_hv>{ccq5p^ayfjbdmIRB30A9 zjw3urmi64I>G@VxkLfh&h}s>Cs&#znE5374J}ZM2TKcT30x3Q4ixPGr4XGL8G;7sN zzW`+5{R28MRKLBrFqC|=#A~{yDaX^r2R2tbFrI7k$iiV&L%gQWicR%#Ymvs8i`(|2 zr{&`s%}Qt|jU$R^{rq}#hj)Um%PU|cTT5pC>~<~fb|g_LS_kf@iN30Q4b|fV-+q7* za3-Ji`5wy;#VlsP1EQy8Rql^q@6J;QwBP=LB!Addx`guop>6WB;vEW&`7a9^RT#NXOSgFyT@NjjK@!W<9(E&BY&e=p_si6 z|J3iYLfaF<Q8is5ihu-Y|vyYqB?O-MGYpiWh&j)O5UrY$5|aV=LW#|;0&-?tD83G<(~IWavL zRdr$;x9-GX@3U`%(0J@xcEuu;4n&tpvq~k?fszG-*KG|%=cdi__3EBfs4y(Iz0Ulk z%YY3n*BG+0p&og*bCw0-r#uMy^Sa1yze~7~SA4hN&YVL3Vl?T!90DRJOEF%;Sm1br z(mdw7H;1}ZYCcIDbQAu>9QLkuJb~SW{wV1G5xuCuuXOk4rD2~kgiCq?hi}fhK&bp? z^}G5onzE=Pzs}{rHw|Z;O%OfX((jQ03JP_$C@mhgKd5yr+D%0JX758lI9RiHl1qj_ z2Ui+Pjx8w*n1{vBe9K&7Py9$OD9T8yTrxF@p&|8EtQ53W)Rw(4 zXidlXod(|o{uaCOn0N1(B9|OuKuZ87Nc4f5%!&kNk=5! zKNoU>+=jZo675{oV9UcD{fJ1aAH~L{r)i-;FB==%YSlvGU&AbA%NyPlZ0I|V@+S|Y z$aaRgT4H^~1^f6Sq@sdmtoM=S_K>gI*`KNy`QG)EMn}nn(kUv{!4}s_xSVJlRwfn8 zz<5VEEwV^VXAj%XhWu_h%kvU@N}|+dHUw@p{!A!?SX>yD`0;rY$#0s8V`()aWjliQ z*AZ?+!kdTMm$D|fNc&2d+z{RW=KHxn^2Ak?%2ehs#zuRWwp9oTBQD`8_FqO{{_Npy zo&LImOzSC1;@|an9v72$UsmV8xfgDzlxoh^zExAnEDl(eFx*F?SNWl@KBVNf! zF0b3wm~Rk8c4+64f83M4%FM!vjGN%Sn$@hE7cCJtS#GF-)37K|-hi5-hk4kJfq1zg zAN)O}^V4%V1ixg;l4VS*kGofKL!%>jBX539PM8i<$q^oF!1n%JFsK@c#fC!mmsD|b znUnjq$=F0|Q2-ZF>3b+q@9EXq>qwS47j}R?lPHbK3!yxqtnDJld&=@2X;`IPp7>FU zGZ*M!XJz@cHnNMPsvEXOo?LtAbkgA5dhhh}B-OSNhL{0AYK^w}w|yjJjud8-|320L zU$J{9^SSPa%G(oZAIiad)vHX9iJY2rz>94`Q9QDZAxDY)&Ztm`c4w6nyX8U&1O82zpDpR=$Q~W(szyaZCZaD2j>w)sfg=K&x5&*aW z=2t&{KUr0iFsaIV+gK#K{<2v}2h@B`>p+Pt*zL)OJVh$6p<#7lNj(jEcd_-9AD zAf=KPm#@C@d#WRGPegc3kk|~lVf{yg#=pq&oHj?9&o$P}6S$5^#Ay@ksj8bnyH|}{ zy!zGMXa2?tq5DNBp(>4ZKoc~01&8`LVfoJsmxm3p^j*@u*S=b0OMD?7a{c*=e05@+}r5PQ_xiD%(2jZddBc-_k6ZCXfJN1ayXJsEZC;QlA z)zPKj;h2-new5<-h`;%Db7i%Ge_h?KueUJAHQ1J>@nbmO>sOdth@ml)v5vGpIv|fe z5tLcjlzw>e(m`9iI4Qq9YGBXC9?`pP^+bU)_~H@S^6#tX&qHfrO=SxdNOnB?UH4If zx>FEWin~%olHf&QU6=5p9MeYX49Pleg=LUY3jkOFhTI?j{d&Zt;VWQ$;n&k=@-t^j zB)fC9{#s}JmPEbZjh0$l?^hFej6!r>|BGnUKg?@gX}BN=b~=?Oc|g{=QN%aIcQ2|v z4zcdR*T%dSdwSQ)xctzMS5qttCv6-S&YfPb{c-G0A{}t94*mu|+%e8~Blxt!}yX%!dB2x_>s{XA+*DVvV?{oRHik;D13) H`j>wLf@vM} literal 0 HcwPel00001 diff --git a/static/img/photo_60x60.jpg b/static/img/photo_60x60.jpg new file mode 100755 index 0000000000000000000000000000000000000000..a9e392964c75ea3ea8c845cb0fa2b190ae267be0 GIT binary patch literal 514 zcwYN|CGcqzD z01GQ4GaC~-iWnFOFfcN*asXAsMHmB_SVUL_6%CD;Ra``cgdG!=lm#*L{lCS)1JuMM z$SlZU&+w~7Mk;Gj49mZ@63naJ7+zg$u-cNqw^o9^H!92O)!K$o@8!D>aCgOVuwDS! zuuNI0@!Y2abG;8T>|$16U|@D}b7h|Ul+kK>6JrUR0|NtFM^6{K^(m%OeHNw{JPiyC zyn>Pr0CKXfUoVV_ nKCs}k=ju9!e*SlxKd`L5!FvG$<>F^;`oqxr*LHqF{r{T)S1fGW literal 0 HcwPel00001 diff --git a/static/img/photo_60x60.psd b/static/img/photo_60x60.psd new file mode 100755 index 0000000000000000000000000000000000000000..137befd0c70eac9e8c229721008dcf71f2b8741f GIT binary patch literal 44528 zcwX&&30xD`_V8ri*b`7(Frt7WkQEXT(6C9AeNnNtHY5W?vYAW-Y-_c(F2z3UzE-VT z5nPap0@ag+P=2RcW1H?5Y+VP>;LP^ncv*G_uO;OIrrRim&~1+ zh-1<+Asl1^0yrbFlZwRwOkN<4ktP%Uu!I}b0kFLOXe@kD|8issfqHv zziXc_Td9ch9Tl3)P1eQ21}0Km zodD;udEsn6mn&lP`4K!pgiydXgKsn)gpqnhUPMM*f>|a=MfnyWh%SP|DJm)oDH4Qe z_4yoLcz8I6%jfXNwfdPBNluQ4 z)5?vgmr3KIjYg#+BAy?U5F?D?#S3}-xHuj!TofKE4(AI5B8ezQBH>|mXGkg zk!j?xm1p?N@w6%Ts_la)^YS`351R9=yQ0{LRJ{_^5bIpgK*?ut9qC7Bzy__#h~{u>NWc?=Gdw7i4^9Ce-~b;H7o31r zgr-A5J~#zJ0e^5pOiXAzFP0x07MlKZKv6*_5-+B*@YjV zInVk5ij7E97Q?F1aZ2Ft22^$!P_@&HP7CIARWPUPg0WhaR-XwbP8fB(j;M~*?JOn; z6Nd?dgxv5jE*64T67l$^kdI+Zp#We)c_tcR5L!xvg<`C=gjfhLLUAY;3;9?WiiM!{ zMFQX(Xeh?Qa5NNiv5<#_d@K}Tp%4p0u@EZ@{71+Wf?PBdVxb8m!a^|`hV!uyqX`cM zp@=WW!f-SM9x3F7i$k$63=2hAD8@pRCOjOY3Fl!U9}5LoD8xdnEUF2g%L@wvUK<2F zJt!s0o;9X z44)qtDhZE?6@?1J<3$p&Bt|Tb6@~G`1VZ5TVsm4@Rv)*{{+&CzHTzj_w`Q5V4a|FR zv>=kx8M@O_(%9HEy*5v&f};%?!(!Od_}DOBcvx64KZIw?#)hs_K8Z>LnD|RL&o_+; z3)X93y~wdH7^B-+z>6IEJBu$nNCtxo-hNLAYYW2!VS`8voWx$3=4oVM-nTvN` z9#NuJ3Xz-MJG7LcMH�o!^lhpwu!A5D6&F6fa<`L}0Z6v$~FBzIuhe^EVxKx~QJjhaAJt zpK>9CF*nO3M<)ZT@Nr5_o_3r`^2>QpyGD{I#v2U?tU!?&u)NL6ZB1>D8`{}4_Bo=h zC)&E=e^Sj3TrIxI4dL2)=L^sxfv_`ls3@!*x~+w~RJtpVx6`in`us~ez1?2lrQ6&1 zy{%bndV?KJ3VOl+gzI*!X9u~Uiz8fxd`0lIqUC?||Fjj*m#o{S4 zHT;@fHbkcmNz)pTOzh(e|3$ZbUKMTB)yRTXFoM|C@GtFF&#C;McP&9MR}{?Uq2H?# zhDQj(UX^P-^TYi=b**fT?7uUk{~z$N=hU?WTbg59|NmrYv~APZJFovAb705h{ zMtL%o0p`4@C{m(>pAp`rt7Kt?Y}9)G-Hk4**;Os=tYljqU$%-}*U<7Ktz#7}HH_q7 z8=}#4Z1465^OtuML5Kr~`HFpc*B{GsY5N}UkSXSG@;YNlA~=h&w6`_wgK_-{OVcdn zaHdjpa{@~Rn7;N)w|*TMlSz1l#Sy$HFlnv|vK9Ft`na z@%$Bw>maDLQy|<%vtNB4R%cV)@DLtL;jxrSH&Z?rixO}+vyFny6sT2*7>0^rP-_7k zeyHg*mkz`7HnioVpfRdc;DVJKsW)g;T1~zs7uLvfbG2GDAEIfD>KHgrtA}kUr~oO+ z1LLD@sZ5>RmJ402)THWUawSq?#(HB|S#f(T+CET>N|S6(Q!t$cC>BrbRA+i8I@9v> zU@Xr>U|nkNc=S_D;L)MJ~XFU_r+u4``eBCWnqs>ym)+A&amsYb*uhR;(FN{ZDWHga9_RoYyc zDoZbu7oyK%j8r8V%vrPonITz=ng(-1%pZhUP6E`KKVbc(gFmng1u%?huTpB@RO~a3 z28#@gqYuV{XifJ(WBA9AsZTsB1^pH|HCJYU(M3a6{OBx@CPCSd0fHetMo7-p8Z`<- zdvj&T5uQa(mR85MF#(hW=h>PBib1q$b2<_$n_qy~q{#-AQVv^cfoms+gyn&V2RJEM zLKD|3{;I2tp>f)5Umb$O9O0cIJycL@)@jCt`-3XeFo0}OMy0%|=-8XwC>zsm}> z0kG)fb0)i<4o*yCvmyJyU9QsutKrf>T%dprz|U~gKwMRX=ukYWH7mCejbn2MOAizT z@$P6m-xLqRXiV{;Xk4Mz0RP6LI_nf_1sXpH;xi{2QNJf7f%x=^O1KEb&wzM;l~Jt( zadf@FQo}OP7m29N`XjKs0L0O`+DV_45ewqLYpG88Ht}4WI08HktyHX5SAsPOdw_f( zn-?A~W+%c$=uO7pG%z^I^a|`@H<_jcf=qSBz~h;3-nQB4`I#>XXxo}%Kc!=BhVwe! zhU<(@y9Rg+Sep?(ZNud*g`k>`AgKGLHeCPJpj&`;+tFlGA1~BjY@XXw!txN*pjLPx z!ApRRybzR~)jaGtQSIL>mdA zJ#SQ>TPDB9z_K#80sI^^FetHE0gBDYV#|&CiKaYkA|Qb^oGVy=c|$%>KWG40i}N87 zG#DBR#Y4lPR45C|f!>1TPywU{b88XwE;JRI4wXWmLJOf~&?;yhR1R%{zJzL^-OzsM zFw_X0gw8@O&{gOL^gZ+ddJO#z*2)x|GmeS##`VGZ;RfOOI59377mrKAW#DpfZ{zZD z8k`aLF788IDQ+Ha8SZmjIj#ymq$1LE(jwA&(st4z(pl0C(ql52>_rYBi^z%O z9P)VbJLK8q&&ZYJdU7-QI{6WWLh+^yqC`31chcDB~LA-%cJ*fljebW1Wmn|8OdEs&~5R z^pmr*v%m9D=P}NR^FN%+og19LcK+3c=@Q~1by2vy@3P!whs!CKd#*HBKUazCTdtE_ z7rAb8ZF0TqMsxFbi*=K^O?F%ER_Au!?U6gvo#&qFu6Cd8Ug7?g`)v=3hrdU>hr(l; z$6AjDkLyeVvmY~-DQAAjT*o}byul)~0$5VkcvdNEGwTHFfv1P3&~v0`vFCEnJ)T#+ z2wwhPQZJR)9Ir3E&UyXTt#>y`H@MrZZdh??bp52Fbhr55=y|Vk+?!S4nz2m(L zz2|z@cwgy3>=D=_y+=`xl|2sixZ9J}b8t_2&yRb4+4E8_e6PS>8NJ@=wYJysUXObF z^d8n**L!L2hTeC5ynKfGjQ3gKv)AWNA7-EEKFU4|`t0lT9ov&FVXN3n*az7U`u6IZ z*w@(i^S&qg{_Y##o9+97Z>8^*e)N9getG>C^gGb+LH|Dell#Bhe`Ehkel$O^UxD9Z zzaxIX_y_op@}J>f<9|D#dw?`xQozQ5%LAMT3>h$Cz?uPP29gJg2Nn+eY~aa2d|+r` zLE!Shra|~YVS|)|J{!~=L<$NI(gdvuIv?y5ED4?%yfOG%h*wBb$Oj=cA@?}_Ib%3; zIY&58xuIMYcOAEd=fNA!`+&ET_ai@$FXu1kpAk3<5(MuHY6TC4gM_efrSL*1Gc-AL zM(BaiCt;#6eb|<;JEH!gw?!*N=fx~>ns~POXgDc6Cj9;I-QoX^2#Y`>zKpm(ICya3 z;EKVwBLgDg$aRs|qkN-eQJ+U$jb=x`9lbjG>X5!eWJA^r`F3c(p^BmFhu)G5l#G{b zlH7~o#^__V$NUl-5&K?jeHOW5Z}`CxP9ri$EF1A{QecukX=gG%d3f^tPhZ**f$j~r!A?HJ0Kkz>}6dGtp78w=mKF*bDU^s(pO40yBn&9C0- z@s{eXJ>y)*$;NGaoAmamw=3TMLzXIABYTu9&0UfEKprb!EdO3HRIxyD2aba0!MF0F z^5*5;&X3BUpMR%dNWr3lyUJMQGUdbZiQ`v||D`asu&l6EHA+>frmEjo*J(U7g_?s} zA8oO=SvN>GU3Yat#Ds+t9_UBt*Bfw#Hx0E23oNFN8wVIaGG3b)J#qQOUyDW-Z7X&! z))XHv2`rgaa%)n;q%Ynfz9WC}V1-)t(GLxwAR4dGDzqr}m$YJAL?!^i1Q~l(Ws} zvd>*OKlc393yKT3FRCs+yfpFB?=4dC z?+?9y{K4o4Hy-LAw*EN#C-0xieir_G;8EJ6uOF))|NhIzzk2_=;ostaANg(6Z?}Fg z`h)Vvk|zV7?0h=n>E%{+Yb*Aff@NI{nC@RWVe5t;A=7#y(tK7!P#{=OL1uabcl>3(Hi*{bd-m)Sri2y1`B#|jp8l8dbn2Ce%1WTqHgd^ez zcp{!eAyY{NCjrQGClLF3@JNz$8Pj*dR6dzC_w%Zle*HZ&_U8(O`VX38DSq=ZA6$DV zH-vhv`SL^mxcOO%_ycQ^ux_WazlDF?Hm%{b@%m2*0SnfBRK4)vnScHK#r8vIZ#){A zH*xx+^*auqyZKl&Y*c>HjKyU&N6z2+#T~-qfwn|UCkmMqimA|-=RpJ-Oz>rr_*3Vy zP!0BHG(QmZ&%LJqU|wvdr`#ZX=to8sp!kO#I0ckg+f5Ol9frW)T2<&;gMc;_S}#FP z1WcwoGz7Y>EYlCU7&ChJAnCx3kJA=kjM*`7`1to0_&rYByl&pIl*3Tq(^Y%D7Osj< zZ-wadR<)k|j#oVLY|>kv)eF|mlll$pKTnzz^jqMZU$ZAQt=Z5DeI!k7ZGH)wQ+KLX zKqL1gY`XNz8F6O(+TXJF4WGCC>$Mq=dTe;QkaKF?`WuTx3m3FPtrs!x?~Ao=Hrm2yQ@cVENC9b~TnL8PV98wo;s`hmSPZ?%#(V(<8;XT8 zApzzxm;_(UeL|9xp+E?|!$rY)V0X08yZI2V2UwAtdR{KBr!_tvH^58-x*Lv%-DgAZ zn(1+TEROc!PiH8xUX0SO1LsMI{>Kyu3UISrpZm{i5V|=U!4*dEg>1{8n1L>^8rP=V zYP^+y&aX{!g$-?kojoP`H21mDKn0*U4{c111cx*8J`sMex) z70i50K!MEdg<>rC^g&93V$5+{z(`vk{ej_$7J{y>Sln?sPRIE_d)ff5{r;UxmQ0@y zBbhLQKCXh^i@|oqk`W}f-TimE>A%0yjWYBeKK6gAF)Fs@E<7e&mX;|?9>7&3*z@=uc%8hWnEsF$d zWrS@SlGP!5m>z~THu)YM@-tw?b4q8TkA>K5sM!dYs%80bnhYsuw@<>#Ho#bp#Lz}+ zZ4k7o&#hoLaC%BqMY0luM4^zV5D9|lmAOU)w)mB^6%#8nSX4tj+9_70HNX;;Dod7c zux{qWn_nuo+4<-mZ;;D$a2)VT6&zE7z}Xo|u>~@{wU7tucA2t?pxASjWq{KKy>H*X zrYMnjoYC|jxiHEL-7AcN3jjx}f1pHOiHKTd$wzPQ1EN%oTb_>ZP@G->1YeuhVLk)MxiaTnwptvM07?Z*{DL4Iu&LtYk%r)YJx5eM6;OE zd}Vbo7}I=s2;++p(_e8~tL!#R zn*;_hOB1w>jcypHWSK5WYx?75OI^X~WXVG}32pq`)!e{<8}^sZR`)jJ$H00pkm~c5 zZSu)djRH1p(3{6VMv_tk$7|3oWU%RM3{$&}wrrfDg+0=ZS_JKY)*fmV>5lz}sNN8- z)*&Uauu5gH(bJOI_I&|!COSI0nlml0;@M<5Wr9fvHkjrI8-C7Naif$9q#zMiw(T6F zT2R2q&|%OZgQkeh%(PU2Wo{X?TGrOFRKm+L#hL27l z7B05ZY#u|wnQW4wZF>?51~{*SDyivf2qg7bmxkQ^`IXy z%#RrLj~I_1QQjKhwyh>{C(We>fH}DJWlkbk>6Abw9aTmRsvCOej0i?|Js96hFnozp z0hz2sK+|$nE@m~HxtvmyR}9%a`BJDU)Y_(123=mev|NQg-_p)LdBuA4HiR40HP~2! zVOj)sVF`3H{WF$OX;ByM#1bk<3l(*+1pYs?1n$*Xf*gWjp0R}5sA8La;*7b}OIv~j zEAnAOJ4>M2kbplZEVF(GYY_iKYuN7>=)IS}-z2iliy{-e) zI1oF6u#*dpkal5+HQsjZ`mm)8>A(pMgUph^;r96FhxhK@xq1ESl}i`SojHA~`RU0Y znx39?Yd&@Q%()Afu3Wu-^UmFS4}X5_1_-~qb^V)`3ul^796xsS@S&#%e`t7m(CyIS zqsNY)Xg+hH<(uobz5}ElfbizED;G{TH6CfG-@9vPZB5PhJ6dbpYIpA1Tild+S=u z*`}ihc5UCfv25+?l`EDl{eFqZ(q$`Fu3lTVaqIS72aYzKZMk;qF7wXyE9aVy)Yn#3 ztXsKs;oLd1OJ~jcVP@+r_tM#O<}O^ia$QALZT*p^b62k4Vcz`a!pWocHI?gEEuLFC zmIS;t7R$ zx#Qk^V@%Hd(X5;?Z@f7!H?MF)@syeKR;;hub*SmWRpym5jrH3rR?VL|8Bri?@50S(rCS~Nv#v@Zo7q8p8`$+R8)`b%dwHsH?omQ-pjY=6Ni4=zl_`LgE z7LP9o6-P>jrHqoPil@z8xv{q4#0BQLfHY1XO3J2$PI^S&-OD>0HE*sr&@C)3^SzAMYko$2Y_yI&wbGBGPx z_x_xfn|2;P<=K3wwqnKX_cY_uE!nUG@Na6^QMP1eaY4@T zD4u_BFE<92M8M-8;#%=c0*T6S^Xl!-iyEF&P&{)<*^Y)LmW6)w@F=c-Z%Ee zvG4>Eh2iSi+n*aXe6)qyvyD0uqoz}c1RU-m)QV#gh!i?TANdS@QN9g5-b|0Tq0cYs zNH2}#`t|CBzLy_2QtF_0(7%A*E`NJzfBuublQoKM0TvS>{-9P^s4aXSDG)sdi@K3Q!M>!4o8ju zd&i43dtC>pad+(K0gkqqCH`uT9v!%2G1|}fZi7Jr^v}kN$7qe9SAqfI_Pw8J_ikQ3 zb+o>&x@zmiO4`<{>bm-)r!L>TN4tHwY5%sem5b-kz4$3@?)=3o%eL)rx_p~{?bQA) zpM5g51eu^~(b9DjkdmpNe70r(scZC>quV~4Vaywwosr&>Mo-Vk9-C*J@!7VcEwr=s zWuF+wrNj&tT@0m(2FIj~Gk#K5f0ouzZjNsu!1x zjR|3QV_tNpF}txtV#by%u0BCOUNs-d9_-)Eg-&gu(5ZBnZvKO_k@;1}>5W_GPRJ1X zGU+5j3!Y9O(V4!Yj0tnMHqwt(eyU3kWxG=exE6?xBT(Jhq3OC$E057Yjy4VCQ1BNa z8lD31X<7%~fp_5l5`5P^^*Oz}%MqcgF{H~er;9PF>rt)ik+7?=v&*rzi?R7HoF89! z2lVwEjvD{>ju&b6x(>@8S(*$%Eb)Y7Lm`CiTw*)MDDZ)0ydV}hy{uPsCFAvq4-3!s zlK!XUlD}AAwxPVD;_1eVo1SiLtss_fC|mypWqld=QMh?a<=L&2$}OA0PsOtJ)Uxu8 zn=7lfRac+i-dauGR#mxqV|f{ML&fH;+qT!#)t%qjT1T$gzHRH~iVf8AO_ker)a~B0 z_xwKU-aWhPc5JKMR8FbbT(!M!&%XU<8z}qt?Wx;dwYh>?v1MD$?tKl14xc|lJ$$HP z-|m`iTPmm_2qm==raxM~@uZzo)LcawBcy*6O;w4d936v5SqZ$0$b+H|(ve z-iqS4@7&jL|} zdwJ(0LZ@R#r=v_4BT}cMS7+l~=OdzHoOECvSO@l1U>)P6W1Mtg9asnU`PjenIQjno DGzh*^ literal 0 HcwPel00001 diff --git a/static/img/switch_minus.gif b/static/img/switch_minus.gif new file mode 100755 index 0000000000000000000000000000000000000000..959a5c2286ba8e2eacac86e2c917a0eec6be90db GIT binary patch literal 119 zcwTe&bhEHb#j0_CC3_2hV$P5M+6@x}jo>+}7XMbwMT4X4?Pe^rc=zXy3 V_Vi;JmFKc_jY6Jkw{tL90|4C(FZ=)i literal 0 HcwPel00001 diff --git a/static/img/switch_plus.gif b/static/img/switch_plus.gif new file mode 100755 index 0000000000000000000000000000000000000000..84ac3532459419c05bf4d53206d14f3864524fde GIT binary patch literal 124 zcwPZ~0E7QWNk%w1VG95Y0J9DNva+)O|NmiOVX3L9u&}VPv9YMAsI#-Po}QkZoSc-D zl&7bst*x!Eudo0A{{R30A^8LW000gEEC2ui01E&M000Cj5P=B}ZELvAIWb*GXq?a$ epecd{z?}>+K*bxazWynxO0029>=rm;j literal 0 HcwPel00001 -- 2.11.4.GIT From e49e6381f6c55e7e31e92027ffee5ededb291fec Mon Sep 17 00:00:00 2001 From: abki Date: Thu, 2 Jul 2009 00:12:39 +0200 Subject: [PATCH 3/6] take care some files are modifier because of the local environnement. new file: .gitignore modified: commands/mylayman.cfg modified: commands/parse.py modified: commands/whoosh_manager.py modified: models.py css for mobile/hanheld (don't work actually : use a subdomain new file: static/css/handheld.css modified: static/css/layout.css modified: static/css/nav.css new file: templates/500.html modified: templates/ebuildfind/base.html modified: templates/ebuildfind/search.html modified: views.py --- .gitignore | 4 +++ commands/mylayman.cfg | 10 +++---- commands/parse.py | 25 ++++-------------- commands/whoosh_manager.py | 5 ++-- models.py | 16 +++++++----- static/css/handheld.css | 5 ++++ static/css/layout.css | 56 +++++++++++++++++++++------------------- static/css/nav.css | 4 --- templates/500.html | 1 + templates/ebuildfind/base.html | 5 ++-- templates/ebuildfind/search.html | 20 ++++++++++++-- views.py | 16 +++++++----- 12 files changed, 91 insertions(+), 76 deletions(-) create mode 100644 .gitignore create mode 100644 static/css/handheld.css create mode 100644 templates/500.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d0a4eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*~ +*pyc +.*\#* +\#* \ No newline at end of file diff --git a/commands/mylayman.cfg b/commands/mylayman.cfg index d0ddbfa..75709d8 100644 --- a/commands/mylayman.cfg +++ b/commands/mylayman.cfg @@ -3,24 +3,24 @@ #----------------------------------------------------------- # Defines the directory where overlays should be installed -storage : /home/timemachine/www/ebuildfnd/ebuildfind/commands/var/ +storage : /home/amir/Desktop/ebuildfind-project/ebuilds/ebuildfind/commands/var/overlays #----------------------------------------------------------- # Remote overlay lists will be stored here # layman will append _md5(url).xml to each filename -cache : %(storage)s/cache +cache : %(storage)s/../cache #----------------------------------------------------------- # The list of locally installed overlays -local_list: /home/timemachine/www/ebuildfnd/ebuildfind/commands/overlays.xml +local_list: %(storage)s/../overlays.xml #----------------------------------------------------------- # Path to the make.conf file that should be modified by # layman -make_conf : %(storage)s/make.conf +make_conf : %(storage)s/../make.conf #----------------------------------------------------------- # URLs of the remote lists of overlays (one per line) or @@ -31,7 +31,7 @@ make_conf : %(storage)s/make.conf # http://mydomain.org/my-layman-list.xml # file:///usr/portage/local/layman/my-list.xml -overlays : file:///home/timemachine/www/ebuildfnd/ebuildfind/commands/overlays.txt +overlays : file://%(storage)s/../../overlays.txt #----------------------------------------------------------- # Proxy support diff --git a/commands/parse.py b/commands/parse.py index 8fff38a..3b346a5 100644 --- a/commands/parse.py +++ b/commands/parse.py @@ -4,24 +4,20 @@ import os, re from django.conf import settings -os.environ['DJANGO_SETTINGS_MODULE'] = 'ebuildfnd.settings' +os.environ['DJANGO_SETTINGS_MODULE'] = 'ebuilds.settings' from layman.debug import Message -from manage_layman import LaymanManager -from ebuildfnd.ebuildfind.models import Ebuild, Overlay +from ebuilds.ebuildfind.models import Ebuild, Overlay from whoosh_manager import WhooshEbuildManager +from manage_layman import LaymanManager -OVERLAYS_BASE = "/home/timemachine/www/ebuildfnd/ebuildfind/commands/var/" -OUT = Message("parser") +OVERLAYS_BASE = settings.ROOT_PATH + "ebuilds/" + "ebuildfind/commands/var/overlays/" class EbuildParser: def __init__(self, overlay, category, app, file_path): path, filename = os.path.split(os.path.realpath(file_path)) - - #OUT.warn("%s\n%s\n%s\n%s" % (overlay, category, app, file_path)) - #OUT.warn("****************************************************") name_version, ext = os.path.splitext(filename) n = len(app) @@ -78,7 +74,6 @@ def ParseEbuilds(): path_overlay = os.path.join(OVERLAYS_BASE, overlay) if exclude_directory(path_overlay, overlay): - print overlay overlay_name = overlay overlay = Overlay.objects.get(name=overlay) @@ -97,7 +92,6 @@ def ParseEbuilds(): for ebuild in ebuilds: if ebuild.endswith(".ebuild"): if exclude_directory(path_overlay_category_app, ebuild): - #OUT.warn(ebuild) path_ebuild = os.path.join(path_overlay_category_app, ebuild) @@ -114,18 +108,10 @@ def ParseEbuilds(): ebuild.iuse = unicode(e.iuse) ebuild.homepage = unicode(e.homepage) ebuild.overlay = overlay - #ebuild.save() + ebuild.save() - whoosh.Update(ebuild) - - i +=1 - print i -def SyncOverlays(): - h = LaymanManager() - h.AddAll() - def ParseOverlays(): h = LaymanManager() overlays = h.List() @@ -142,7 +128,6 @@ def ParseOverlays(): o.save() def main(): - #SyncOverlays() ParseOverlays() ParseEbuilds() diff --git a/commands/whoosh_manager.py b/commands/whoosh_manager.py index e4acb95..b713390 100644 --- a/commands/whoosh_manager.py +++ b/commands/whoosh_manager.py @@ -11,7 +11,7 @@ from django.conf import settings os.environ['DJANGO_SETTINGS_MODULE'] = 'ebuilds.settings' -INDEX_BASE = settings.ROOT_PATH + "/ebuildfind/commands/var/index" +INDEX_BASE = settings.ROOT_PATH + "ebuilds" + "/ebuildfind/commands/var/index" class WhooshEbuildManager: def __init__(self, reset=False): @@ -48,8 +48,9 @@ class WhooshEbuildManager: content = ' '.join(content) - writer.add_document(permalink=ebuild.permalink(), + writer.add_document(permalink=unicode(ebuild.id), content=content) + print ">", ebuild.overlay.name, ">>> ", ebuild.name writer.commit() def Search(self, query): diff --git a/models.py b/models.py index 7e062d6..2e6741e 100644 --- a/models.py +++ b/models.py @@ -1,10 +1,12 @@ from django.db import models + + class Overlay(models.Model): name = models.CharField(max_length=255) description = models.TextField() link = models.URLField() - + def __repr__(self): return self.name @@ -16,14 +18,14 @@ class Ebuild(models.Model): category = models.CharField(max_length=255) version = models.CharField(max_length=255) description = models.TextField() - keywords = models.CharField(max_length=255) - license = models.CharField(max_length=255) - iuse = models.CharField(max_length=255) + keywords = models.TextField(max_length=255) + license = models.TextField(max_length=255) + iuse = models.TextField(max_length=255) homepage = models.URLField() overlay = models.ForeignKey(Overlay) - - def permalink(self): + + def path(self): return "/%s/%s/%s/%s" % (self.overlay.name, self.category, self.name, self.version) def get_absolute_url(self): - return "/search/?q=%s" % self.name \ No newline at end of file + return "/search/?q=%s" % self.name diff --git a/static/css/handheld.css b/static/css/handheld.css new file mode 100644 index 0000000..1f42243 --- /dev/null +++ b/static/css/handheld.css @@ -0,0 +1,5 @@ +* { + position: static !important; + float: none !important; + background: none !important; +} \ No newline at end of file diff --git a/static/css/layout.css b/static/css/layout.css index 61def42..f1c901d 100755 --- a/static/css/layout.css +++ b/static/css/layout.css @@ -13,6 +13,7 @@ body { h7 { font-size: 11px; font-weight: normal;} .post { overflow : hidden; } + /* anchors ----------------------------------------------- */ @@ -49,38 +50,39 @@ h7 { font-size: 11px; font-weight: normal;} text-align: center; } -/* boxes ------------------------------------------------ */ - -/* paragraphs, quotes and lists ------------------------------------------------ */ - -/* menus ------------------------------------------------ */ - -/* submenus ------------------------------------------------ */ - -/* section menus +/* results ----------------------------------------------- */ +.ebuild { + background-color: #DDDDFF; + margin: 0px; + padding: 10px; + margin-bottom: 10px; +} -/* table ------------------------------------------------ */ +ul, li { + list-style-type: none; + margin: 0px; + padding: 0px; -/* forms ------------------------------------------------ */ +} -/* articles ------------------------------------------------ */ +.ebuild:hover { + background-color: #7A5ADA; + color: black; +} -/* site information ------------------------------------------------ */ +.ebuild { + font-size: 1.2em; +} -/* AJAX sliding shelf ------------------------------------------------ */ +.ebuild .description { + font-size: 1.5em; +} -/* Accordian ------------------------------------------------ */ +.ebuild .homepage { + float: right; +} -/* Mootools Kwicks ------------------------------------------------ */ +.ebuild .path { + float: left; +} \ No newline at end of file diff --git a/static/css/nav.css b/static/css/nav.css index 7cb8440..53bff8d 100755 --- a/static/css/nav.css +++ b/static/css/nav.css @@ -165,7 +165,3 @@ ul.nav li.secondary:hover a:hover { background:#555; } ul.nav li.secondary:hover a:active {background:#444;} - -#results li:hover { - font-weight: bold; -} \ No newline at end of file diff --git a/templates/500.html b/templates/500.html new file mode 100644 index 0000000..2bf3dd1 --- /dev/null +++ b/templates/500.html @@ -0,0 +1 @@ +Sory Fattal Error diff --git a/templates/ebuildfind/base.html b/templates/ebuildfind/base.html index a332a1d..4ef4227 100644 --- a/templates/ebuildfind/base.html +++ b/templates/ebuildfind/base.html @@ -7,9 +7,10 @@ - - + + diff --git a/templates/ebuildfind/search.html b/templates/ebuildfind/search.html index ced17d8..9ecf917 100644 --- a/templates/ebuildfind/search.html +++ b/templates/ebuildfind/search.html @@ -11,8 +11,24 @@ {% endif %}
    - {% for result in results %} -
  • {{result}}
  • + {% for ebuild in results %} +
  • +
    +
      +
    • {{ebuild.path}}
    • +
    • homepage
    • +
      + {% if ebuild.keywords %} +
    • {{ebuild.keywords}}
    • + {% endif %} + {% if ebuild.iuse %} +
    • {{ebuild.iuse}}
    • + {% endif %} +
    • {{ebuild.license}}
    • +
    • {{ebuild.description}}
    • +
    +
    +
  • {% endfor %}
diff --git a/views.py b/views.py index cc17e83..aabd229 100644 --- a/views.py +++ b/views.py @@ -1,14 +1,10 @@ - - - - - from commands.whoosh_manager import WhooshEbuildManager from django.shortcuts import render_to_response from planet import Parser -whoosh = WhooshEbuildManager() +from models import Ebuild, Overlay +whoosh = WhooshEbuildManager() def index(request): GPlanet = Parser("http://planet.gentoo.org/atom.xml") @@ -25,6 +21,11 @@ def index(request): return render_to_response("ebuildfind/index.html", response) +overlay = {} + +def add_overlay(name, description): + overlay["name"] = description + def search(request): response = {"error":"Query should be at least 3 caracters long"} query = "" @@ -43,6 +44,7 @@ def search(request): response["results"] = list() for result in results: - response["results"].append(result["permalink"]) + ebuild = Ebuild.objects.get(id=result["permalink"]) + response["results"].append(ebuild) return render_to_response("ebuildfind/search.html", response) -- 2.11.4.GIT From 6cc312bddb2f6b8babb1abcb7e4edfd98417ddd0 Mon Sep 17 00:00:00 2001 From: abki Date: Fri, 3 Jul 2009 14:55:17 +0200 Subject: [PATCH 4/6] mysql FTS updated templates sitemap --- commands/.gitignore | 1 + commands/parse.py | 18 ++++--- models.py | 106 +++++++++++++++++++++++++++++++++++++-- templates/ebuildfind/base.html | 12 +++-- templates/ebuildfind/search.html | 21 ++++---- urls.py | 39 ++++++++------ views.py | 20 ++++---- 7 files changed, 166 insertions(+), 51 deletions(-) create mode 100644 commands/.gitignore rewrite urls.py (65%) diff --git a/commands/.gitignore b/commands/.gitignore new file mode 100644 index 0000000..032c0df --- /dev/null +++ b/commands/.gitignore @@ -0,0 +1 @@ +overlays.xml \ No newline at end of file diff --git a/commands/parse.py b/commands/parse.py index 3b346a5..4a61dc1 100644 --- a/commands/parse.py +++ b/commands/parse.py @@ -10,7 +10,6 @@ from layman.debug import Message from ebuilds.ebuildfind.models import Ebuild, Overlay -from whoosh_manager import WhooshEbuildManager from manage_layman import LaymanManager OVERLAYS_BASE = settings.ROOT_PATH + "ebuilds/" + "ebuildfind/commands/var/overlays/" @@ -67,14 +66,14 @@ def ParseEbuilds(): i = 0 Ebuild.objects.all().delete() overlays = os.listdir(OVERLAYS_BASE) - - whoosh = WhooshEbuildManager(True) - + for overlay in overlays: path_overlay = os.path.join(OVERLAYS_BASE, overlay) if exclude_directory(path_overlay, overlay): overlay_name = overlay + print "is present", overlay_name + overlay = Overlay.objects.get(name=overlay) categories = os.listdir(path_overlay) @@ -110,17 +109,18 @@ def ParseEbuilds(): ebuild.overlay = overlay ebuild.save() - whoosh.Update(ebuild) + ebuild.index() def ParseOverlays(): h = LaymanManager() overlays = h.List() - - for name, overlay in overlays.items() : + + for name, overlay in overlays.items(): """ check if new overlay is ready """ o = Overlay.objects.all().filter(name=name) - + print "add ? > ", name if not o: + print "added !", name o = Overlay() o.name = name o.description = overlay["description"] @@ -128,7 +128,9 @@ def ParseOverlays(): o.save() def main(): + print "# >>> Parse Overlays" ParseOverlays() + print "# >>> Parse Ebuilds" ParseEbuilds() if __name__ == "__main__": diff --git a/models.py b/models.py index 2e6741e..5f1ee15 100644 --- a/models.py +++ b/models.py @@ -1,19 +1,112 @@ +import re, string + from django.db import models +from django.contrib.contenttypes.models import ContentType +from django.contrib.contenttypes import generic + +PUNCTUATION_REGEX = re.compile('[' + re.escape(string.punctuation) + ']') +FULL_TEXT_MIN_LENGTH = 3 + +FULL_TEXT_STOP_WORDS = frozenset([ + 'a', 'about', 'according', 'accordingly', 'affected', 'affecting', 'after', + 'again', 'against', 'all', 'almost', 'already', 'also', 'although', + 'always', 'am', 'among', 'an', 'and', 'any', 'anyone', 'apparently', 'are', + 'arise', 'as', 'aside', 'at', 'away', 'be', 'became', 'because', 'become', + 'becomes', 'been', 'before', 'being', 'between', 'both', 'briefly', 'but', + 'by', 'came', 'can', 'cannot', 'certain', 'certainly', 'could', 'did', 'do', + 'does', 'done', 'during', 'each', 'either', 'else', 'etc', 'ever', 'every', + 'following', 'for', 'found', 'from', 'further', 'gave', 'gets', 'give', + 'given', 'giving', 'gone', 'got', 'had', 'hardly', 'has', 'have', 'having', + 'here', 'how', 'however', 'i', 'if', 'in', 'into', 'is', 'it', 'itself', + 'just', 'keep', 'kept', 'knowledge', 'largely', 'like', 'made', 'mainly', + 'make', 'many', 'might', 'more', 'most', 'mostly', 'much', 'must', 'nearly', + 'necessarily', 'neither', 'next', 'no', 'none', 'nor', 'normally', 'not', + 'noted', 'now', 'obtain', 'obtained', 'of', 'often', 'on', 'only', 'or', + 'other', 'our', 'out', 'owing', 'particularly', 'past', 'perhaps', 'please', + 'poorly', 'possible', 'possibly', 'potentially', 'predominantly', 'present', + 'previously', 'primarily', 'probably', 'prompt', 'promptly', 'put', + 'quickly', 'quite', 'rather', 'readily', 'really', 'recently', 'regarding', + 'regardless', 'relatively', 'respectively', 'resulted', 'resulting', + 'results', 'said', 'same', 'seem', 'seen', 'several', 'shall', 'should', + 'show', 'showed', 'shown', 'shows', 'significantly', 'similar', 'similarly', + 'since', 'slightly', 'so', 'some', 'sometime', 'somewhat', 'soon', + 'specifically', 'state', 'states', 'strongly', 'substantially', + 'successfully', 'such', 'sufficiently', 'than', 'that', 'the', 'their', + 'theirs', 'them', 'then', 'there', 'therefore', 'these', 'they', 'this', + 'those', 'though', 'through', 'throughout', 'to', 'too', 'toward', 'under', + 'unless', 'until', 'up', 'upon', 'use', 'used', 'usefully', 'usefulness', + 'using', 'usually', 'various', 'very', 'was', 'we', 'were', 'what', 'when', + 'where', 'whether', 'which', 'while', 'who', 'whose', 'why', 'widely', + 'will', 'with', 'within', 'without', 'would', 'yet', 'you']) + +class Index(models.Model): + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content = models.TextField() + + content_object = generic.GenericForeignKey() + + @staticmethod + def full_text_index(text): + if text: + text = PUNCTUATION_REGEX.sub(' ', text) + words = text.lower().split() + words = set(words) + words -= FULL_TEXT_STOP_WORDS + + for word in list(words): + if len(word) < FULL_TEXT_MIN_LENGTH: + words.remove(word) + else: + words = set() + return words + + @staticmethod + def index(obj): + keywords = set() + + properties = obj._meta.fields + for property in properties: + isurlfield = not isinstance(property, models.URLField) + istext = isinstance(property, models.CharField) or isinstance(property, models.TextField) + if istext and isurlfield: + text = property.value_from_object(obj) + mykeywords = Index.full_text_index(text) + keywords = keywords.union(mykeywords) + + text = " ".join(keywords) + # Create or Update + ctype = ContentType.objects.get_for_model(obj) + try: + index = Index.objects.get(content_type__pk=ctype.id, object_id=obj.id) + index.content = text + index.save() + except: + index = Index(content_object=obj, content=text) + index.save() + return index + +class Searchable(object): + @staticmethod + def search(cls, query): + ctype = ContentType.objects.get_for_model(cls) + return Index.objects.filter(content__search=query).filter(content_type=ctype) + + def index(self): + return Index.index(self) class Overlay(models.Model): name = models.CharField(max_length=255) description = models.TextField() link = models.URLField() - - def __repr__(self): + + def __unicode__(self): return self.name - def get_absolute_url(self): - return "/search/?q=%s" % self.name -class Ebuild(models.Model): +class Ebuild(Searchable, models.Model): name = models.CharField(max_length=255) category = models.CharField(max_length=255) version = models.CharField(max_length=255) @@ -29,3 +122,6 @@ class Ebuild(models.Model): def get_absolute_url(self): return "/search/?q=%s" % self.name + + def __unicode__(self): + return self.name diff --git a/templates/ebuildfind/base.html b/templates/ebuildfind/base.html index 4ef4227..b20327b 100644 --- a/templates/ebuildfind/base.html +++ b/templates/ebuildfind/base.html @@ -27,11 +27,15 @@ {% block help %} -

This is a search engine for ebuilds, it looks for the query in the overlay name, - category, description, application name and the exact version name. Give it a try now and here

+

This is a search engine for ebuilds, it looks for the query in the + category, description, application name. Give it a + try now + and here

+

3 July 09': The search engine is now supported by + Mysql FTS in boolean mode, try this out.

28 June 09': Some ebuilds and overlays are missing please - notify me bugs at google - code project page

+ notify me bugs + at my email adress

{% endblock %}
diff --git a/templates/ebuildfind/search.html b/templates/ebuildfind/search.html index 9ecf917..45c3dd4 100644 --- a/templates/ebuildfind/search.html +++ b/templates/ebuildfind/search.html @@ -11,21 +11,24 @@ {% endif %}
    - {% for ebuild in results %} + {% for result in results %}
    • -
    • {{ebuild.path}}
    • -
    • homepage
    • +
    • {{result.content_object.path}}
    • +
    • homepage
    • - {% if ebuild.keywords %} -
    • {{ebuild.keywords}}
    • +
    • overlay + homepage
    • +
      + {% if result.content_object.keywords %} +
    • {{result.content_object.keywords}}
    • {% endif %} - {% if ebuild.iuse %} -
    • {{ebuild.iuse}}
    • + {% if result.content_object.iuse %} +
    • {{result.content_object.iuse}}
    • {% endif %} -
    • {{ebuild.license}}
    • -
    • {{ebuild.description}}
    • +
    • {{result.content_object.license}}
    • +
    • {{result.content_object.description}}
  • diff --git a/urls.py b/urls.py dissimilarity index 65% index 41d3376..e2db4a3 100644 --- a/urls.py +++ b/urls.py @@ -1,15 +1,24 @@ -from django.conf.urls.defaults import * -import views - -urlpatterns = patterns('', - # Example: - - - # Uncomment the admin/doc line below and add 'django.contrib.admindocs' - # to INSTALLED_APPS to enable admin documentation: - # (r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - (r'^search/', views.search), - (r'^$', views.index), -) +from django.conf.urls.defaults import * +import views +from django.contrib.sitemaps import GenericSitemap +from models import Ebuild +from django.contrib import admin + +admin.autodiscover() + +info_dict = { + 'queryset': Ebuild.objects.all(), +} + +sitemaps = { + 'ebuild': GenericSitemap(info_dict), +} + +urlpatterns = patterns('', + + (r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}), + (r'^sitemap-(?P
    .+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}), + (r'^search/', views.search), + (r'^$', views.index), + (r'^admin/(.*)', admin.site.root), +) diff --git a/views.py b/views.py index aabd229..d10edcf 100644 --- a/views.py +++ b/views.py @@ -2,9 +2,11 @@ from commands.whoosh_manager import WhooshEbuildManager from django.shortcuts import render_to_response from planet import Parser -from models import Ebuild, Overlay +from models import Ebuild, Index -whoosh = WhooshEbuildManager() +import re, string + +PUNCTUATION_REGEX = re.compile('[' + re.escape(string.punctuation.replace("-", "").replace("+", "")) + ']') def index(request): GPlanet = Parser("http://planet.gentoo.org/atom.xml") @@ -13,6 +15,7 @@ def index(request): GGoogle = Parser("http://news.google.fr/news?pz=1&ned=us&hl=en&q=gentoo+AND+(linux+OR+OS+OR+Operating+System+OR+GNU)&output=rss") response = dict() + response['GGoogle'] = GGoogle response['GNews'] = GNews response['GOverlays'] = GOverlays @@ -33,18 +36,15 @@ def search(request): if request.method == 'GET': try: query = request.GET["q"] + query = PUNCTUATION_REGEX.sub(' ', query) except: pass - + if(len(query)>2): response["error"] = False response["query"] = query - - results = whoosh.Search(query) - response["results"] = list() - - for result in results: - ebuild = Ebuild.objects.get(id=result["permalink"]) - response["results"].append(ebuild) + results = Ebuild.search(Ebuild, query) + response["results"] = results + response["nb"] = len(results) return render_to_response("ebuildfind/search.html", response) -- 2.11.4.GIT From 0ffaf6f87171ef5f4790b2941e723f5624ec7352 Mon Sep 17 00:00:00 2001 From: abki Date: Sun, 19 Jul 2009 17:58:11 +0200 Subject: [PATCH 5/6] regex hack to get 2 & 3 letter words to work modified: models.py modified: planet.py modified: static/css/layout.css modified: templates/ebuildfind/base.html modified: templates/ebuildfind/search.html modified: views.py --- models.py | 6 +++++- planet.py | 4 +--- static/css/layout.css | 9 ++++++++- templates/ebuildfind/base.html | 37 +++++++++++++++++++------------------ templates/ebuildfind/search.html | 38 ++++++++++++++++++++++++++++++++++---- views.py | 19 +++++++++++++------ 6 files changed, 80 insertions(+), 33 deletions(-) diff --git a/models.py b/models.py index 5f1ee15..0f83e62 100644 --- a/models.py +++ b/models.py @@ -5,7 +5,6 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes import generic PUNCTUATION_REGEX = re.compile('[' + re.escape(string.punctuation) + ']') -FULL_TEXT_MIN_LENGTH = 3 FULL_TEXT_STOP_WORDS = frozenset([ 'a', 'about', 'according', 'accordingly', 'affected', 'affecting', 'after', @@ -94,6 +93,11 @@ class Searchable(object): ctype = ContentType.objects.get_for_model(cls) return Index.objects.filter(content__search=query).filter(content_type=ctype) + @staticmethod + def regex(cls, query): + ctype = ContentType.objects.get_for_model(cls) + return Index.objects.filter(content__regex=query).filter(content_type=ctype) + def index(self): return Index.index(self) diff --git a/planet.py b/planet.py index 6c9abd5..d6ca3c6 100644 --- a/planet.py +++ b/planet.py @@ -2,8 +2,6 @@ import shelve from feedcache.cache import Cache -import pdb - from django.template.defaultfilters import truncatewords_html from django.utils.encoding import smart_unicode @@ -39,7 +37,7 @@ class Parser: """ def __init__(self, url, summary=False): - storage = shelve.open(".feedcache") + storage = shelve.open("/home/timemachine/.feedcache") try : fc = Cache(storage) self.feed = fc.fetch(url) diff --git a/static/css/layout.css b/static/css/layout.css index f1c901d..4d9900f 100755 --- a/static/css/layout.css +++ b/static/css/layout.css @@ -7,7 +7,6 @@ body { background: #FFF; color: #333; font-size: 11px; - padding: 50px 0 40px; } h7 { font-size: 11px; font-weight: normal;} @@ -23,6 +22,13 @@ h7 { font-size: 11px; font-weight: normal;} /* headings ----------------------------------------------- */ +#header { + font-size: 13px; + background: #5218EC; + padding: 5px; + margin-bottom: 50px; +} + /* search-box ----------------------------------------------- */ @@ -85,4 +91,5 @@ ul, li { .ebuild .path { float: left; + font-weight: bold; } \ No newline at end of file diff --git a/templates/ebuildfind/base.html b/templates/ebuildfind/base.html index b20327b..73d45bf 100644 --- a/templates/ebuildfind/base.html +++ b/templates/ebuildfind/base.html @@ -10,11 +10,14 @@ - +
    +
    @@ -26,26 +29,20 @@ - {% block help %} -

    This is a search engine for ebuilds, it looks for the query in the - category, description, application name. Give it a - try now - and here

    -

    3 July 09': The search engine is now supported by - Mysql FTS in boolean mode, try this out.

    -

    28 June 09': Some ebuilds and overlays are missing please - notify me bugs - at my email adress

    - {% endblock %} +
    +
    -
    +
    {% block results %}{% endblock %}
    +
    + {% block adv %}{% endblock %} +
    @@ -99,10 +96,10 @@
    -

    Google News

    +

    Identi.ca community

    - - {% for post in GGoogle %} +

    Check out ebuildfind@identi.ca

    + {% for post in identica %}
    {{ post.title }}
    {{ post.content|safe }}
    @@ -115,12 +112,16 @@
    +
    + {% block advbottom %} + {% endblock %} +

    "Gentoo" and "G" logo are the property of Gentoo Foundation, Inc.

    This website is made with - django and whoosh - hosted by alwaysdata.com

    + django and mysql FTS hosted by + alwaysdata.com

    + +{% endblock %} + +{% block advbottom %} + + +{% endblock %} \ No newline at end of file diff --git a/views.py b/views.py index d10edcf..0317b71 100644 --- a/views.py +++ b/views.py @@ -12,15 +12,15 @@ def index(request): GPlanet = Parser("http://planet.gentoo.org/atom.xml") GOverlays = Parser("http://overlays.gentoo.org/rss20.xml") GNews = Parser("http://www.gentoo.org/rdf/en/gentoo-news.rdf") - GGoogle = Parser("http://news.google.fr/news?pz=1&ned=us&hl=en&q=gentoo+AND+(linux+OR+OS+OR+Operating+System+OR+GNU)&output=rss") + identica = Parser("https://identi.ca/api/laconica/groups/timeline/gentoo.atom") response = dict() - response['GGoogle'] = GGoogle + response['identica'] = identica response['GNews'] = GNews response['GOverlays'] = GOverlays response['GPlanet'] = GPlanet - + return render_to_response("ebuildfind/index.html", response) @@ -39,12 +39,19 @@ def search(request): query = PUNCTUATION_REGEX.sub(' ', query) except: pass - - if(len(query)>2): + + if(len(query)>3): response["error"] = False response["query"] = query results = Ebuild.search(Ebuild, query) response["results"] = results response["nb"] = len(results) - + + elif len(query) in (2, 3): + response["error"] = False + response["query"] = query + results = Ebuild.regex(Ebuild, query) + response["results"] = results + response["nb"] = len(results) + return render_to_response("ebuildfind/search.html", response) -- 2.11.4.GIT From bfe399add6c6462b1b7d695ae391b8e4fc09322e Mon Sep 17 00:00:00 2001 From: abki Date: Sun, 19 Jul 2009 19:33:46 +0200 Subject: [PATCH 6/6] switched back to whoosh with haystack --- LICENSE | 674 +++++++++++++++++++++ README | 32 + models.py | 163 +---- planet.py | 35 +- search_indexes.py | 8 + static/css/layout.css | 27 + templates/ebuildfind/base.html | 17 +- templates/ebuildfind/search.html | 6 +- .../search/indexes/ebuildfind/ebuild_text.txt | 6 + templates/search/search.html | 84 +++ urls.py | 13 +- views.py | 36 +- 12 files changed, 885 insertions(+), 216 deletions(-) create mode 100644 LICENSE create mode 100644 README rewrite models.py (83%) create mode 100644 search_indexes.py create mode 100644 templates/search/indexes/ebuildfind/ebuild_text.txt create mode 100644 templates/search/search.html diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d1e6a12 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + ebuildfind Copyright (C) 2009 Amirouche BOUBEKKI + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..b3e5ce3 --- /dev/null +++ b/README @@ -0,0 +1,32 @@ +Dependencies +------------ + + - haystack + - whoosh + - feedcache + - feedparser + - Django 1.0.2 + - a database + +Setting up haystack search +-------------------------- + + * install haystack from http://github.com/toastdriven/django-haystack/tree/master + * install whoosh with easy_install Whoosh + * Add haystack to your INSTALLED_APPS + * then refer to the documentation +http://haystacksearch.org/docs/tutorial.html#modify-your-settings-py + +Setting up ebuildfind +--------------------- + + * Setup haystack with whoosh + * run: layman -c ebuildfind/commands/mylayman.cfg -a ALL + * run: python manage.py reindex ebuildfind + +further updates +--------------- + + * run: layman -c ebuildfind/commands/mylayman.cfg -s ALL + * run: python manage.py reindex ebuildfind + \ No newline at end of file diff --git a/models.py b/models.py dissimilarity index 83% index 0f83e62..f3eabb3 100644 --- a/models.py +++ b/models.py @@ -1,131 +1,32 @@ -import re, string - -from django.db import models -from django.contrib.contenttypes.models import ContentType -from django.contrib.contenttypes import generic - -PUNCTUATION_REGEX = re.compile('[' + re.escape(string.punctuation) + ']') - -FULL_TEXT_STOP_WORDS = frozenset([ - 'a', 'about', 'according', 'accordingly', 'affected', 'affecting', 'after', - 'again', 'against', 'all', 'almost', 'already', 'also', 'although', - 'always', 'am', 'among', 'an', 'and', 'any', 'anyone', 'apparently', 'are', - 'arise', 'as', 'aside', 'at', 'away', 'be', 'became', 'because', 'become', - 'becomes', 'been', 'before', 'being', 'between', 'both', 'briefly', 'but', - 'by', 'came', 'can', 'cannot', 'certain', 'certainly', 'could', 'did', 'do', - 'does', 'done', 'during', 'each', 'either', 'else', 'etc', 'ever', 'every', - 'following', 'for', 'found', 'from', 'further', 'gave', 'gets', 'give', - 'given', 'giving', 'gone', 'got', 'had', 'hardly', 'has', 'have', 'having', - 'here', 'how', 'however', 'i', 'if', 'in', 'into', 'is', 'it', 'itself', - 'just', 'keep', 'kept', 'knowledge', 'largely', 'like', 'made', 'mainly', - 'make', 'many', 'might', 'more', 'most', 'mostly', 'much', 'must', 'nearly', - 'necessarily', 'neither', 'next', 'no', 'none', 'nor', 'normally', 'not', - 'noted', 'now', 'obtain', 'obtained', 'of', 'often', 'on', 'only', 'or', - 'other', 'our', 'out', 'owing', 'particularly', 'past', 'perhaps', 'please', - 'poorly', 'possible', 'possibly', 'potentially', 'predominantly', 'present', - 'previously', 'primarily', 'probably', 'prompt', 'promptly', 'put', - 'quickly', 'quite', 'rather', 'readily', 'really', 'recently', 'regarding', - 'regardless', 'relatively', 'respectively', 'resulted', 'resulting', - 'results', 'said', 'same', 'seem', 'seen', 'several', 'shall', 'should', - 'show', 'showed', 'shown', 'shows', 'significantly', 'similar', 'similarly', - 'since', 'slightly', 'so', 'some', 'sometime', 'somewhat', 'soon', - 'specifically', 'state', 'states', 'strongly', 'substantially', - 'successfully', 'such', 'sufficiently', 'than', 'that', 'the', 'their', - 'theirs', 'them', 'then', 'there', 'therefore', 'these', 'they', 'this', - 'those', 'though', 'through', 'throughout', 'to', 'too', 'toward', 'under', - 'unless', 'until', 'up', 'upon', 'use', 'used', 'usefully', 'usefulness', - 'using', 'usually', 'various', 'very', 'was', 'we', 'were', 'what', 'when', - 'where', 'whether', 'which', 'while', 'who', 'whose', 'why', 'widely', - 'will', 'with', 'within', 'without', 'would', 'yet', 'you']) - -class Index(models.Model): - content_type = models.ForeignKey(ContentType) - object_id = models.PositiveIntegerField() - content = models.TextField() - - content_object = generic.GenericForeignKey() - - @staticmethod - def full_text_index(text): - if text: - text = PUNCTUATION_REGEX.sub(' ', text) - words = text.lower().split() - words = set(words) - words -= FULL_TEXT_STOP_WORDS - - for word in list(words): - if len(word) < FULL_TEXT_MIN_LENGTH: - words.remove(word) - else: - words = set() - return words - - @staticmethod - def index(obj): - keywords = set() - - properties = obj._meta.fields - for property in properties: - isurlfield = not isinstance(property, models.URLField) - istext = isinstance(property, models.CharField) or isinstance(property, models.TextField) - if istext and isurlfield: - text = property.value_from_object(obj) - mykeywords = Index.full_text_index(text) - keywords = keywords.union(mykeywords) - - text = " ".join(keywords) - - # Create or Update - ctype = ContentType.objects.get_for_model(obj) - - try: - index = Index.objects.get(content_type__pk=ctype.id, object_id=obj.id) - index.content = text - index.save() - except: - index = Index(content_object=obj, content=text) - index.save() - return index - -class Searchable(object): - @staticmethod - def search(cls, query): - ctype = ContentType.objects.get_for_model(cls) - return Index.objects.filter(content__search=query).filter(content_type=ctype) - - @staticmethod - def regex(cls, query): - ctype = ContentType.objects.get_for_model(cls) - return Index.objects.filter(content__regex=query).filter(content_type=ctype) - - def index(self): - return Index.index(self) - -class Overlay(models.Model): - name = models.CharField(max_length=255) - description = models.TextField() - link = models.URLField() - - def __unicode__(self): - return self.name - - -class Ebuild(Searchable, models.Model): - name = models.CharField(max_length=255) - category = models.CharField(max_length=255) - version = models.CharField(max_length=255) - description = models.TextField() - keywords = models.TextField(max_length=255) - license = models.TextField(max_length=255) - iuse = models.TextField(max_length=255) - homepage = models.URLField() - overlay = models.ForeignKey(Overlay) - - def path(self): - return "/%s/%s/%s/%s" % (self.overlay.name, self.category, self.name, self.version) - - def get_absolute_url(self): - return "/search/?q=%s" % self.name - - def __unicode__(self): - return self.name +import re, string + +from django.db import models + +class Overlay(models.Model): + name = models.CharField(max_length=255) + description = models.TextField() + link = models.URLField() + + def __unicode__(self): + return self.name + + +class Ebuild(models.Model): + name = models.CharField(max_length=255) + category = models.CharField(max_length=255) + version = models.CharField(max_length=255) + description = models.TextField() + keywords = models.TextField(max_length=255) + license = models.TextField(max_length=255) + iuse = models.TextField(max_length=255) + homepage = models.URLField() + overlay = models.ForeignKey(Overlay) + + def path(self): + return "/%s/%s/%s/%s" % (self.overlay.name, self.category, self.name, self.version) + + def get_absolute_url(self): + return "/search/?q=%s" % self.name + + def __unicode__(self): + return self.name diff --git a/planet.py b/planet.py index d6ca3c6..b84bc28 100644 --- a/planet.py +++ b/planet.py @@ -2,8 +2,10 @@ import shelve from feedcache.cache import Cache +from django.conf import settings + from django.template.defaultfilters import truncatewords_html -from django.utils.encoding import smart_unicode + def TryEncoding(content): for body_charset in 'UTF-8', 'US-ASCII', 'ISO-8859-1', : @@ -15,20 +17,17 @@ def TryEncoding(content): if not type(content) is str: pass - def GetContent(feed): if hasattr(feed, "content"): return feed.content[0]["value"] else: return feed.summary - class Parser: """ "http://planet.gentoo.org/atom.xml" "http://overlays.gentoo.org/rss20.xml" - "http://www.gentoo.org/rdf/en/gentoo-news.rdf" - >>> f = Parser() + >>> f = Parser("http://www.gentoo.org/rdf/en/gentoo-news.rdf") >>> f.GetTitle() u'Planet Gentoo' >>> f.GetLink() @@ -37,7 +36,7 @@ class Parser: """ def __init__(self, url, summary=False): - storage = shelve.open("/home/timemachine/.feedcache") + storage = shelve.open(settings.ROOT_PATH + "feedcache") try : fc = Cache(storage) self.feed = fc.fetch(url) @@ -71,27 +70,3 @@ class Parser: def __iter__(self): return self - -def _test(): - """ - import doctest, ebuilds.ebuildfind.planet as planet - return doctest.testmod(planet) - - "http://news.google.fr/news?pz=1&ned=us&hl=en&q=gentoo+AND+(linux+OR+OS+OR+Operating+System+OR+GNU)&output=rss" - "http://www.gentoo.org/rdf/en/gentoo-news.rdf" - "http://planet.gentoo.org/atom.xml" - "http://overlays.gentoo.org/rss20.xml" - """ - - f = Parser("http://planet.gentoo.org/atom.xml", True) - - print f.GetTitle() - print f.GetLink() - - for e in f: - print e["title"] - print e["content"] - print e["link"] - -if __name__ == "__main__": - _test() diff --git a/search_indexes.py b/search_indexes.py new file mode 100644 index 0000000..3c897ad --- /dev/null +++ b/search_indexes.py @@ -0,0 +1,8 @@ +import datetime +from haystack import indexes +from haystack import site +from models import Ebuild + +class EbuildIndex(indexes.SearchIndex): + text = indexes.CharField(document=True, use_template=True) +site.register(Ebuild, EbuildIndex) diff --git a/static/css/layout.css b/static/css/layout.css index 4d9900f..d6d81ba 100755 --- a/static/css/layout.css +++ b/static/css/layout.css @@ -89,7 +89,34 @@ ul, li { float: right; } + +.ebuild:hover .path { + color: #00FF00; +} + .ebuild .path { float: left; font-weight: bold; +} + +.info { + background: #5218EC; + color: black; + +} + +.info a { + color : #00FF00; + text-decoration: none; +} + +.info a:hover { + color : #00FF00; + text-decoration: underline; +} + + +#bottom { + background: #5218EC; + color: black; } \ No newline at end of file diff --git a/templates/ebuildfind/base.html b/templates/ebuildfind/base.html index 73d45bf..537ef64 100644 --- a/templates/ebuildfind/base.html +++ b/templates/ebuildfind/base.html @@ -26,7 +26,10 @@
    - + +
    @@ -46,50 +49,45 @@
    +
    {% block info %}

    Overlays Planet

    - {% for post in GOverlays %}
    {{ post.title }}
    {{ post.content|safe }}
    {% endfor %} -
    +

    Gentoo Planet

    - {% for post in GPlanet %}
    {{ post.title }}
    {{ post.content|truncatewords_html:100|safe }}
    - {% endfor %} - + {% endfor %}
    -

    Gentoo News

    - {% for post in GNews %}
    {{ post.title }}
    {{ post.content|safe }}
    {% endfor %} -
    @@ -111,6 +109,7 @@ {% endblock %}
    +
    {% block advbottom %} diff --git a/templates/ebuildfind/search.html b/templates/ebuildfind/search.html index fad7d27..83f3b3c 100644 --- a/templates/ebuildfind/search.html +++ b/templates/ebuildfind/search.html @@ -19,7 +19,7 @@
  • homepage
  • overlay - homepage
  • + homepage
    {% if result.content_object.keywords %}
  • keywords: {{result.content_object.keywords}}
  • @@ -31,8 +31,6 @@
  • {{result.content_object.description}}
-
-
{% endfor %} @@ -67,4 +65,4 @@ google_ad_height = 15; -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/search/indexes/ebuildfind/ebuild_text.txt b/templates/search/indexes/ebuildfind/ebuild_text.txt new file mode 100644 index 0000000..e457452 --- /dev/null +++ b/templates/search/indexes/ebuildfind/ebuild_text.txt @@ -0,0 +1,6 @@ +{{ object.name }} +{{ object.category }} +{{ object.description }} +{{ object.overlay.name }} +{{ object.overlay.description }} + diff --git a/templates/search/search.html b/templates/search/search.html new file mode 100644 index 0000000..2c5a2e2 --- /dev/null +++ b/templates/search/search.html @@ -0,0 +1,84 @@ +{% extends "ebuildfind/base.html" %} + +{% block search-value%}{{query}}{% endblock %} + +{% block results %} + {% if page.object_list %} +
    + {% for result in page.object_list %} +
  • +
    +
      +
    • {{result.object.path}}
    • +
    • homepage
    • +
      +
    • overlay + homepage
    • +
      + {% if result.object.keywords %} +
    • keywords: {{result.object.keywords}}
    • + {% endif %} + {% if result.object.iuse %} +
    • iuse: {{result.object.iuse}}
    • + {% endif %} +
    • license: {{result.object.license}}
    • +
    • {{result.object.description}}
    • +
    +
    +
  • + {% endfor %} +
+ + + + {% else %} +

No results found.

+ {% endif %} + + +{% endblock %} + +{% block info %} +{% endblock %} + +{% block adv %} + + +{% endblock %} + +{% block advbottom %} + + +{% endblock %} diff --git a/urls.py b/urls.py index e2db4a3..4f8877c 100644 --- a/urls.py +++ b/urls.py @@ -1,10 +1,10 @@ from django.conf.urls.defaults import * -import views from django.contrib.sitemaps import GenericSitemap from models import Ebuild -from django.contrib import admin +import views -admin.autodiscover() + +#from django.contrib import admin info_dict = { 'queryset': Ebuild.objects.all(), @@ -15,10 +15,9 @@ sitemaps = { } urlpatterns = patterns('', - (r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}), - (r'^sitemap-(?P
.+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}), - (r'^search/', views.search), + (r'^sitemap-(?P
.+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}), + (r'^search/', include('haystack.urls')), (r'^$', views.index), - (r'^admin/(.*)', admin.site.root), +# (r'^admin/(.*)', admin.site.root), ) diff --git a/views.py b/views.py index 0317b71..8ba9114 100644 --- a/views.py +++ b/views.py @@ -1,8 +1,7 @@ -from commands.whoosh_manager import WhooshEbuildManager from django.shortcuts import render_to_response from planet import Parser -from models import Ebuild, Index +from models import Ebuild import re, string @@ -22,36 +21,3 @@ def index(request): response['GPlanet'] = GPlanet return render_to_response("ebuildfind/index.html", response) - - -overlay = {} - -def add_overlay(name, description): - overlay["name"] = description - -def search(request): - response = {"error":"Query should be at least 3 caracters long"} - query = "" - - if request.method == 'GET': - try: - query = request.GET["q"] - query = PUNCTUATION_REGEX.sub(' ', query) - except: - pass - - if(len(query)>3): - response["error"] = False - response["query"] = query - results = Ebuild.search(Ebuild, query) - response["results"] = results - response["nb"] = len(results) - - elif len(query) in (2, 3): - response["error"] = False - response["query"] = query - results = Ebuild.regex(Ebuild, query) - response["results"] = results - response["nb"] = len(results) - - return render_to_response("ebuildfind/search.html", response) -- 2.11.4.GIT