EVOLUTION-MANAGER
Edit File: r2spec_obj.py
#-*- coding: utf-8 -*- # 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, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # (C) 2011 - Pierre-Yves Chibon <pingou@pingoured.fr> """ Main functions for R2spec """ import argparse import ConfigParser import logging import os import re import sys import pwd from urlparse import urlparse from r2spec.build import Build from r2spec.rpackage import RPackage from r2spec.spec import Spec from r2spec import * # Initial simple logging stuff LOG = get_logger() if '--debug' in sys.argv: LOG.setLevel(logging.DEBUG) elif '--verbose' in sys.argv: LOG.setLevel(logging.INFO) def setup_parser(prog): """ Set the main arguments. :arg prog, the name of the program """ parser = argparse.ArgumentParser(usage='%(prog)s [options]', prog=prog) parser.add_argument('--version', action='version', version='%(prog)s ' +VERSION) # General connection options parser.add_argument('-p', '--package', help='Name of the R package to package.') parser.add_argument('-u', '--url', help='URL to the sources of a R package.') parser.add_argument('-s', '--sources', help='Path to local sources of a R package.') parser.add_argument('--no-check', action='store_true', help='Do not include the %%check section in the generated spec file.') parser.add_argument('--no-suggest', action='store_true', help='Do not include the dependencies marked as \'Suggest\' by the source as dependencies of the RPM.') parser.add_argument('--force-dl', action='store_true', help='Enforce the download of the source, even if they are already on the system.') parser.add_argument('--keep-sources', action='store_true', help='The extracted source on the current directory will not be removed.') parser.add_argument('--keep-logs', action='store_true', help='Keep the log file generated while building the rpm') parser.add_argument('--repo', default=None, help='Name of the repository as described in the configuration file.') parser.add_argument('--name', default=None, help='Name of the packager to use in the spec (overrides local configuration file).') parser.add_argument('--email', default=None, help='Email of the packager to use in the spec (overrides local configuration file).') parser.add_argument('--verbose', action='store_true', help='Give more info about what is going on.') parser.add_argument('--debug', action='store_true', help='Output bunches of debugging info.') if prog == 'R2rpm': setup_r2rpm_parser(parser) return parser def setup_r2rpm_parser(parser): """ This function setup the argument specific to R2rpm. :arg parser, a argparse.ArgumentParers object to which new argument will be added. """ parser.add_argument('--force-spec', action='store_true', help="Force the generation of a new spec file.") parser.add_argument('--mock-config', help="Specify the mock configuration to use.") parser.add_argument('--mock-resultdir', help="Specify the mock result directory.") return parser def create_conf(configfile): """Check if the provided configuration file exists, generate the folder if it does not and return True or False according to the initial check. :arg configfile, name of the configuration file looked for. """ if not os.path.exists(configfile): dirn = os.path.dirname(configfile) if not os.path.exists(dirn): os.makedirs(dirn) return True return False def save_config(configfile, parser): """"Save the configuration into the specified file. :arg configfile, name of the file in which to write the configuration :arg parser, ConfigParser object containing the configuration to write down. """ conf = open(configfile, 'w') parser.write(conf) conf.close() class Settings(object): """ R2spec user config Setting""" # Editor to use in the spec try: packager = os.getlogin() except OSError: # os.getlogin() raises an exception when the session is not # in /var/run/utmp (non-login sessions) if os.environ.has_key('LOGNAME'): packager = os.environ['LOGNAME'] else: packager = pwd.getpwuid(os.getuid())[0] # Editor email to use in the spec email = '' def __init__(self): """Constructor of the Settings object. This instanciate the Settings object and load into the _dict attributes the default configuration which each available option. """ self._dict = { 'packager': self.packager, 'email': self.email, } self.load_config('.config/r2spec/settings', 'main') def load_config(self, configfile, sec): """Load the configuration in memory. :arg configfile, name of the configuration file loaded. :arg sec, section of the configuration retrieved. """ parser = ConfigParser.ConfigParser() configfile = os.environ['HOME'] + "/" + configfile is_new = create_conf(configfile) parser.read(configfile) if not parser.has_section(sec): parser.add_section(sec) self.populate(parser, sec) if is_new: save_config(configfile, parser) def set(self, key, value): """ Set the value to the given key in the settings. :arg key, name of the parameter to set from the settings. :arg value, value of the parameter to set from the settings. """ if not key in self._dict.keys(): raise KeyError(key) self._dict[key] = value def get(self, key): """ Return the associated with the given key in the settings. :arg key, name of the parameter to retrieve from the settings. """ if not key in self._dict.keys(): raise KeyError(key) return self._dict[key] def populate(self, parser, section): """"Set option values from a INI file section. :arg parser: ConfigParser instance (or subclass) :arg section: INI file section to read use. """ if parser.has_section(section): opts = set(parser.options(section)) else: opts = set() for name in self._dict.iterkeys(): value = None if name in opts: value = parser.get(section, name) parser.set(section, name, value) self._dict[name] = value else: parser.set(section, name, self._dict[name]) class R2spec(object): """ R2spec object. """ def __init__(self): """ Constructor. Set the logger. """ self.log = get_logger() def main(self, args): """ main fonction for R2spec. This is the method which actually runs R2spec and generate the spec file according to the argument given. """ settings = Settings() if args.name: settings.set('packager', args.name) if args.email: settings.set('email', args.email) if args.package: pack = RPackage(re.sub('^R-', '', args.package)) pack.search_package_in_repo() elif args.url: pack = RPackage(source0=args.url) source = args.url.rsplit('/', 1)[1] pack.source = source name = source.split('_')[0] pack.name = name version = source.split('_')[1].split('.tar')[0] pack.up_version = version version = version.replace('-', '_') pack.down_version = version if args.repo: pack.set_repo(args.repo) elif args.sources: pack = RPackage() fullpath = os.path.expanduser(args.sources) sourcedir = get_rpm_tag('_sourcedir') if '/' in fullpath: sources = fullpath.rsplit('/', 1)[1] else: sources = fullpath pack.source = sources pack.source0 = sources if sources not in os.listdir(sourcedir): move_sources(fullpath, sources) name, version = sources.split('_', 1) pack.name = name version = version.split('.tar')[0] pack.up_version = version version = version.replace('-', '_') pack.down_version = version if args.repo: pack.set_repo(args.repo) else: raise R2specError('Not enough argument given, see -h/--help') if args.package or args.url: pack.download(args.force_dl) pack.extract_sources() pack.get_description() pack.determine_arch() if not args.keep_sources: pack.remove_sources() spec = Spec(settings, pack, no_check=args.no_check, no_suggest=args.no_suggest) spec.fill_spec_info() spec.get_template() spec.write_spec(True) return pack class R2rpm(R2spec): """ R2rpm object. """ def __init__(self): """ Constructor. Set the logger. """ super(R2rpm, self).__init__() self.pack = RPackage() self.settings = Settings() self.build = Build() self.spec = Spec(self.settings, self.pack) def __check_build_output(self): """ Handle the output from the build, if it succeeded we stop otherwise the parse the error and act accordingly. Return False if the build was successful, retun True otherwise. """ specfile = self.spec.get_specfile() if self.build.outcode == 0: self.log.info("RPM %s done" % specfile) # Get the list of rpm generated self.build.get_rpm() print "RPM generated:" print "\n".join(self.build.rpm) return False else: return True def main(self, args): """ main fonction for R2rpm. This is the method which actually runs R2rpm, it generates the spec files, cleans its %files section, build it and fill again the %files section. """ specfile = '' if args.package: self.pack.name = re.sub('^R-', '', args.package) self.spec.package = self.pack specfile = self.spec.get_specfile() self.pack.search_package_in_repo() elif args.url: source = args.url.rsplit('/', 1)[1] self.pack.source = source name = source.split('_')[0] self.pack.name = name version = source.split('_')[1].split('.tar')[0] self.pack.up_version = version version = version.replace('-', '_') self.pack.down_version = version if args.repo: self.pack.set_repo(args.repo) elif args.sources: fullpath = os.path.expanduser(args.sources) if '/' in fullpath: sources = fullpath.rsplit('/', 1)[1] else: sources = fullpath name = sources.split('_')[0] self.pack.name = name self.spec.package = self.pack specfile = self.spec.get_specfile() else: raise R2specError('Not enough argument given, see -h/--help') if args.force_spec \ or (not os.path.exists(specfile) \ and not os.path.isfile(specfile)): # Generate the spec file self.pack = super(R2rpm, self).main(args) else: self.log.info('Spec file "%s" is already there, no need to regenerate it' % specfile) if args.package or args.url: self.pack.download(args.force_dl) self.spec = Spec(self.settings, self.pack) specfile = self.spec.get_specfile() self.spec.read_specfile() self.spec.clean_files_section() self.spec.write_spec() print 'Building... %s' % self.pack.name self.build.build(specfile, mock_config=args.mock_config, mock_resultdir=args.mock_resultdir) if self.__check_build_output(): try: files = self.build.parse_error(specfile) if files == 1: return 1 if len(files) != 0: self.spec.add_files(files) # Write down the spec file self.spec.write_spec() # Rebuild the package when build has failed the first time if self.build.outcode: # == 1 when build failed and 0 when build passed print 'Re-building... %s' % self.pack.name self.build.build(specfile, mock_config=args.mock_config, mock_resultdir=args.mock_resultdir) self.__check_build_output() except BuildDepencenciesError, err: print 'Missing dependencies to build %s' % self.pack.name self.log.info(err) return 1 except BuildError, err: print 'An error occured during the build of %s' % self.pack.name self.log.debug('Build ERROR: %s' % err) return 1 if not args.keep_logs: self.build.remove_logs() return 0