#!/usr/bin/env python # -*- coding: utf-8 -*- """ g-octave ~~~~~~~~ Main script of g-Octave. :copyright: (c) 2009-2010 by Rafael Goncalves Martins :license: GPL-2, see LICENSE for more details. """ from __future__ import print_function has_fetch = True __issue_tracker = 'Mail to: rafael@rafaelmartins.eng.br' import sys # This block ensures that ^C interrupts are handled quietly. # Code snippet from Portage try: import signal def exithandler(signum,frame): signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGTERM, signal.SIG_IGN) sys.exit(1) signal.signal(signal.SIGINT, exithandler) signal.signal(signal.SIGTERM, exithandler) except KeyboardInterrupt: sys.exit(1) import getpass import os import optparse import portage import subprocess out = portage.output.EOutput() current_dir = os.path.dirname(os.path.realpath(__file__)) if os.path.exists(os.path.join(current_dir, '..', 'g_octave')): sys.path.insert(0, os.path.join(current_dir, '..')) from g_octave.log import Log log = Log('g-octave') log.info('Initializing...') import g_octave def main(): parser = optparse.OptionParser( usage = '%prog [options] ', version = '%prog ' + g_octave.__version__, description = g_octave.__description__ ) parser.add_option( '-l', '--list', action = 'store_true', dest = 'list', default = False, help = 'show a list of packages available to install (separed by categories) and exit' ) parser.add_option( '--list-raw', action = 'store_true', dest = 'list_raw', default = False, help = 'show a list of packages available to install (a package per line, without colors) and exit' ) parser.add_option( '-i', '--info', action = 'store_true', dest = 'info', default = False, help = 'show a description of the required package and exit' ) parser.add_option( '-p', '--pretend', action = 'store_true', dest = 'pretend', default = False, help = 'don\'t (un)merge packages, only create ebuilds and solve the dependencies' ) parser.add_option( '-a', '--ask', action = 'store_true', dest = 'ask', default = False, help = 'ask to confirmation before perform (un)merges' ) parser.add_option( '-v', '--verbose', action = 'store_true', dest = 'verbose', default = False, help = 'package manager\'s makes a lot of noise.' ) parser.add_option( '-1', '--oneshot', action = 'store_true', dest = 'oneshot', default = False, help = 'do not add the packages to the world file for later updating.' ) parser.add_option( '-u', '--update', action = 'store_true', dest = 'update', default = False, help = 'try to update a package or all the installed packages' ) parser.add_option( '-s', '--search', action = 'store_true', dest = 'search', default = False, help = 'search for packages with some term on the name (regular expressions allowed)' ) parser.add_option( '-C', '--unmerge', action = 'store_true', dest = 'unmerge', default = False, help = 'try to unmerge a package instead of merge' ) parser.add_option( '--scm', action = 'store_true', dest = 'scm', default = False, help = 'enable the installation of the current live version of a package, if disabled on the configuration file' ) parser.add_option( '--no-scm', action = 'store_true', dest = 'no_scm', default = False, help = 'disable the installation of the current live version of a package, if enabled on the configuration file' ) parser.add_option( '-f', '--force', action = 'store_true', dest = 'force', default = False, help = 'forces the recreation of the ebuilds' ) parser.add_option( '--force-all', action = 'store_true', dest = 'force_all', default = False, help = 'forces the recreation of the overlay and of the ebuilds' ) parser.add_option( '--no-colors', action = 'store_false', dest = 'colors', default = True, help = 'don\'t use colors on the CLI' ) parser.add_option( '--sync', action = 'store_true', dest = 'sync', default = False, help = 'search for updates of the package database, patches and auxiliary files' ) parser.add_option( '--config', action = 'store_true', dest = 'config', default = False, help = 'return a value from the configuration file (/etc/g-octave.cfg)' ) options, args = parser.parse_args() if not options.colors: portage.output.nocolor() from g_octave.config import Config from g_octave.fetch import fetch conf_prefetch = Config(True) if options.config: try: log.info('Returning configuration data.') print(conf_prefetch.__getattr__(args[0])) except: log.error('Invalid configuration key: %s' % args[0]) return os.EX_DATAERR return os.EX_OK from g_octave.package_manager import Portage, Pkgcore, Paludis if conf_prefetch.package_manager == 'portage': log.info('Your package manager is: Portage') pkg_manager = Portage(options.ask, options.verbose, options.pretend, options.oneshot, not options.colors) elif conf_prefetch.package_manager == 'pkgcore': log.info('Your package manager is: Pkgcore') pkg_manager = Pkgcore(options.ask, options.verbose, options.pretend, options.oneshot, not options.colors) elif conf_prefetch.package_manager == 'paludis': log.info('Your package manager is: Paludis') pkg_manager = Paludis(options.ask, options.verbose, options.pretend, options.oneshot, not options.colors) else: log.error('Invalid package manager: %s' % conf_prefetch.package_manager) out.eerror('Invalid package manager: %s' % conf_prefetch.package_manager) return os.EX_CONFIG # checking if the package manager is installed if not pkg_manager.is_installed(): log.error('Package manager not installed: %s' % conf_prefetch.package_manager) out.eerror('Package manager not installed: %s' % conf_prefetch.package_manager) return os.EX_CONFIG # checking if the current user is allowed to run g-octave current_user = getpass.getuser() if current_user not in pkg_manager.allowed_users(): log.error( 'The current user (%s) can\'t run the current selected ' 'package manager (%s)' % (current_user, conf_prefetch.package_manager) ) out.eerror( 'The current user (%s) can\'t run the current selected ' 'package manager (%s)' % (current_user, conf_prefetch.package_manager) ) return os.EX_NOPERM # checking if our overlay is correctly added to PORTDIR_OVERLAY if not pkg_manager.check_overlay(conf_prefetch.overlay, out): log.error('Overlay not properly configured.') return os.EX_CONFIG if has_fetch: log.info('You can fetch package databases.') updates = fetch() if updates is None: log.error('Invalid db_mirror value.') out.eerror('Your db_mirror value is invalid. Change it, or leave it empty to use the default.') return os.EX_CONFIG # checking if we have a package database if updates.need_update() and not options.sync: log.error('No package database found.') out.eerror('Please run "g-octave --sync" to download a package database!') return os.EX_USAGE if options.sync: log.info('Searching updates ...') out.einfo('Searching updates ...') if not updates.fetch_db(): log.info('No updates available') out.einfo('No updates available') updates.extract() return os.EX_OK else: log.info('You can\'t fetch package databases.') if options.sync: log.error('You can\'t fetch package databases.') out.eerror('"--sync" not available, please install g-octave-9999 if you want this.') return os.EX_USAGE conf = Config() from g_octave.description import Description from g_octave.description_tree import DescriptionTree from g_octave.ebuild import Ebuild, EbuildException from g_octave.overlay import create_overlay if options.list_raw: log.info('Raw list of available packages.') tree = DescriptionTree() for pkg in tree.packages(): print(pkg) return os.EX_OK elif options.list: log.info('Listing available packages.') tree = DescriptionTree() print(portage.output.blue('Available packages:')) print() packages = tree.list() for category in packages: print( portage.output.blue('Category:'), portage.output.white(category) ) print() for pkg in packages[category]: print( portage.output.green(' Package:'), portage.output.white(pkg) ) print( portage.output.green(' Available versions:'), portage.output.red(', '.join(packages[category][pkg])) ) print() return os.EX_OK elif options.update: pass elif len(args) == 0: log.error('You need provide an argument.') out.eerror('You need provide an argument.') return os.EX_USAGE elif len(args) > 1: log.error('g-octave can install only one package at once.') out.eerror('At this moment g-octave can install only one package at once') return os.EX_USAGE # if we're alive yet, we have a package to install! :D # or a search to do! :P # check if use said that want the live version in some place use_scm = conf.use_scm.lower() == 'true' or options.scm # if the user said that don't want the live version with --no-scm, # this is mandatory if options.no_scm: use_scm = False create_overlay(options.force_all) if len(args) > 0: if options.search: log.info('Searching for packages: %s' % args[0]) tree = DescriptionTree() print( portage.output.blue('Search results for '), portage.output.white(args[0]), portage.output.blue(':\n'), sep = '' ) packages = tree.search(args[0]) for pkg in packages: print( portage.output.green('Package:'), portage.output.white(pkg) ) print( portage.output.green('Available versions:'), portage.output.red(', '.join(packages[pkg])) ) print() return os.EX_OK log.info('Processing a package: %s' % args[0]) try: ebuild = Ebuild( args[0], # pkg atom options.force or options.force_all, # force pkg_manager=pkg_manager, # package manager scm = use_scm, # want to use the live version? ) except EbuildException: log.error('Package not found: %s' % args[0]) out.eerror('Package not found: %s' % args[0]) return os.EX_DATAERR if options.info: log.info('Returning info about the package.') pkg = ebuild.description() print(portage.output.blue('Package:'), portage.output.white(str(pkg.name))) print(portage.output.blue('Version:'), portage.output.white(str(pkg.version))) print(portage.output.blue('Date:'), portage.output.white(str(pkg.date))) print(portage.output.blue('Maintainer:'), portage.output.white(str(pkg.maintainer))) print(portage.output.blue('Description:'), portage.output.white(str(pkg.description))) print(portage.output.blue('Categories:'), portage.output.white(str(pkg.categories))) print(portage.output.blue('License:'), portage.output.white(str(pkg.license))) print(portage.output.blue('Url:'), portage.output.white(str(pkg.url))) return os.EX_OK atom, catpkg = ebuild.create() if options.unmerge: log.info('Calling the package manager to uninstall the package.') ret = pkg_manager.uninstall_package(atom, catpkg) elif options.update: if len(args) > 0: log.info('Calling the package manager to update the package.') ret = pkg_manager.update_package(atom, catpkg) else: log.info('Calling the package manager to update all the installed packages.') ret = pkg_manager.update_package() else: log.info('Calling the package manager to install the package.') ret = pkg_manager.install_package(atom, catpkg) if ret != os.EX_OK: log.error('"%s" returned an error.' % conf.package_manager) out.eerror('"%s" returned an error.' % conf.package_manager) sys.exit(ret) if options.unmerge and len(pkg_manager.post_uninstall) > 0: log.info(' '.join(pkg_manager.post_uninstall)) print() for i in pkg_manager.post_uninstall: out.einfo(i) log.info('Finishing g-octave... all OK!') return os.EX_OK if __name__ == '__main__': from g_octave.exception import * return_code = os.EX_OK try: return_code = main() except ConfigException as error: log.error('Config class error - %s' % error) out.eerror('Config class error - %s' % error) return_code = os.EX_CONFIG except DescriptionException as error: log.error('Description class error - %s' % error) out.eerror('Description class error - %s' % error) return_code = os.EX_SOFTWARE except DescriptionTreeException as error: log.error('DescriptionTree class error - %s' % error) out.eerror('DescriptionTree class error - %s' % error) return_code = os.EX_SOFTWARE except EbuildException as error: log.error('Ebuild class error - %s' % error) out.eerror('Ebuild class error - %s' % error) return_code = os.EX_SOFTWARE except FetchException as error: log.error('Fetch module error - %s' % error) out.eerror('Fetch module error - %s' % error) return_code = os.EX_SOFTWARE except OSError as error: log.error('Operating System error - %s' % error) out.eerror('Operating System error - %s' % error) out.eerror('Try run "g-octave" as root.') return_code = os.EX_OSERR except IOError as error: log.error('I/O error - %s' % error) out.eerror('I/O error - %s' % error) out.eerror('Try run "g-octave" as root.') return_code = os.EX_IOERR except KeyError as error: log.error('Key error - %s' % error) out.eerror('Key error - %s' % error) out.eerror('Probably you have more than one overlay configured to use with g-octave') out.eerror('Try remove the oldest and maintain only the overlay actually in use.') return_code = os.EX_SOFTWARE except Exception as error: log.error('Unknown error - %s' % error) out.eerror('Unknown error - %s' % error) return_code = os.EX_SOFTWARE if return_code not in [os.EX_OK, os.EX_CONFIG, os.EX_USAGE, os.EX_DATAERR, os.EX_NOPERM]: out.einfo('If you fell that this is a bug, please report to us.') out.einfo(__issue_tracker) sys.exit(return_code)