#!/usr/bin/python """Copyright 2011 Gentoo Foundation Distributed under the terms of the GNU General Public License v2 """ from __future__ import print_function # Meta __author__ = "Corentin Chary (iksaif)" __email__ = "corentin.chary@gmail.com" __version__ = "git" __productname__ = "euscan" __description__ = "A tool to detect new upstream releases." # Imports import sys import getopt import errno import httplib from portage.output import white, yellow, turquoise, green from portage.exception import AmbiguousPackageName from gentoolkit import pprinter as pp from gentoolkit.eclean.search import (port_settings) from gentoolkit.errors import GentoolkitException from euscan import CONFIG, output from euscan.scan import scan_upstream # Globals def exit_helper(status): if CONFIG["format"]: print(output.get_formatted_output()) sys.exit(status) def setup_signals(): """This block ensures that ^C interrupts are handled quietly.""" import signal def exithandler(signum, frame): signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGTERM, signal.SIG_IGN) print() exit_helper(errno.EINTR) signal.signal(signal.SIGINT, exithandler) signal.signal(signal.SIGTERM, exithandler) signal.signal(signal.SIGPIPE, signal.SIG_DFL) def print_version(): """Output the version info.""" print("%s (%s) - %s" \ % (__productname__, __version__, __description__)) print() print("Author: %s <%s>" % (__author__, __email__)) print("Copyright 2011 Gentoo Foundation") print("Distributed under the terms of the GNU General Public License v2") def print_usage(_error=None, help=None): """Print help message. May also print partial help to stderr if an error from {'options'} is specified.""" out = sys.stdout if _error: out = sys.stderr if not _error in ('global-options', 'packages',): _error = None if not _error and not help: help = 'all' if _error in ('global-options',): output.eerror("Wrong option on command line.\n") if _error in ('packages',): output.eerror("You need to specify exactly one package.\n") print(white("Usage:"), file=out) if _error in ('global-options', 'packages',) or help == 'all': print(" " + turquoise(__productname__), yellow("[options]"), green(" [ [...]]"), file=out) if _error in ('global-options',) or help == 'all': print(" " + turquoise(__productname__), yellow("[--help, --version]"), file=out) print(file=out) if _error in ('global-options',) or help: print("Available ", yellow("options") + ":", file=out) print(yellow(" -C, --nocolor") + " - turn off colors on output", file=out) print(yellow(" -q, --quiet") + " - be as quiet as possible", file=out) print(yellow(" -h, --help") + " - display the help screen", file=out) print(yellow(" -V, --version") + " - display version info", file=out) print(file=out) print(yellow(" -1, --oneshot") + " - stop as soon as a new version is found", file=out) print(yellow(" -b, --brute-force=") + " - define the brute force " + yellow("") + " (default: 2)\n" + " " * 29 + "bigger levels will generate more versions numbers\n" + " " * 29 + "0 means disabled", file=out) print(yellow(" -f, --format=") + " - define the output " + yellow("") + " (available: json)", file=out) print(file=out) if _error in ('packages',) or help: print(green(" package") + " - the packages (or ebuilds) you want to scan", file=out) print(file=out) #print( "More detailed instruction can be found in", #turquoise("`man %s`" % __productname__), file=out) class ParseArgsException(Exception): """For parseArgs() -> main() communications.""" def __init__(self, value): self.value = value def __str__(self): return repr(self.value) def parse_args(): """Parse the command line arguments. Raise exceptions on errors. Returns packages and affects the CONFIG dict. """ def option_switch(opts): """local function for interpreting command line options and setting options accordingly""" return_code = True for o, a in opts: if o in ("-h", "--help"): raise ParseArgsException('help') elif o in ("-V", "--version"): raise ParseArgsException('version') elif o in ("-C", "--nocolor"): CONFIG['nocolor'] = True pp.output.nocolor() elif o in ("-q", "--quiet"): CONFIG['quiet'] = True CONFIG['verbose'] = 0 elif o in ("-1", "--oneshot"): CONFIG['oneshot'] = True elif o in ("-b", "--brute-force"): CONFIG['brute-force'] = int(a) elif o in ("-v", "--verbose") and not CONFIG['quiet']: CONFIG['verbose'] += 1 elif o in ("-f", "--format"): CONFIG['format'] = a CONFIG['nocolor'] = True pp.output.nocolor() else: return_code = False return return_code # here are the different allowed command line options (getopt args) getopt_options = {'short': {}, 'long': {}} getopt_options['short']['global'] = "hVCqv1bf:" getopt_options['long']['global'] = [ "help", "version", "nocolor", "quiet", "verbose", "oneshot", "brute-force=", "format=" ] short_opts = getopt_options['short']['global'] long_opts = getopt_options['long']['global'] opts_mode = 'global' # apply getopts to command line, show partial help on failure try: opts, args = getopt.getopt(sys.argv[1:], short_opts, long_opts) except: raise ParseArgsException(opts_mode + '-options') # set options accordingly option_switch(opts) if len(args) < 1: raise ParseArgsException('packages') return args def main(): """Parse command line and execute all actions.""" CONFIG['nocolor'] = ( port_settings["NOCOLOR"] in ('yes', 'true') or not sys.stdout.isatty() ) if CONFIG['nocolor']: pp.output.nocolor() # parse command line options and actions try: queries = parse_args() except ParseArgsException as e: if e.value == 'help': print_usage(help='all') exit_helper(0) elif e.value[:5] == 'help-': print_usage(help=e.value[5:]) exit_helper(0) elif e.value == 'version': print_version() exit_helper(0) else: print_usage(e.value) exit_helper(errno.EINVAL) if CONFIG['verbose'] > 2: httplib.HTTPConnection.debuglevel = 1 for query in queries: ret = [] output.set_query(query) try: ret = scan_upstream(query) except AmbiguousPackageName as e: pkgs = e.args[0] output.eerror("\n".join(pkgs)) from os.path import basename # To get the short name output.error( "The short ebuild name '%s' is ambiguous. Please specify" % basename(pkgs[0]), "one of the above fully-qualified ebuild names instead." ) exit_helper(1) except GentoolkitException as err: output.eerror('%s: %s' % (query, str(err))) exit_helper(1) except Exception as err: output.eerror('%s: %s' % (query, str(err))) exit_helper(1) if not CONFIG['quiet'] and not CONFIG['format']: print() if ret is not None: if len(ret) > 0: for cp, url, version, handler in ret: output.result(cp, version, url, handler) elif not CONFIG['quiet']: output.ewarn( "Didn't find any new version, check package's homepage " + "for more informations" ) output.set_query(None) if __name__ == "__main__": setup_signals() main() exit_helper(0)