def download(self, env): """ Downloads the last CVS code, or from a specific date. """ import tempfile try: tempdir = tempfile.mkdtemp(dir=env.srcrepo) except OSError as e: raise TaskError('Could not create temporary directory %s, Error: %s' % (env.srcrepo, e)) env.run(['cvs', '-d', self.attribute('root').value, 'login'], directory=tempdir) checkout_options = [] if not self.attribute('date').value is None: checkout_options.extend(['-D', self.attribute('date').value]) env.run(['cvs', '-d', self.attribute('root').value, 'checkout'] + checkout_options + [self.attribute('module').value], directory=tempdir) if self.attribute('checkout_directory').value is not None: actual_checkout_dir = self.attribute('checkout_directory').value else: actual_checkout_dir = self.attribute('module').value import os import shutil try: os.rename(os.path.join(tempdir, actual_checkout_dir), env.srcdir) shutil.rmtree(tempdir) except AttributeError as e: raise TaskError('Atribute type error expected String, Error: %s' % e)
def download(self, env): import tempfile import os try: tempdir = tempfile.mkdtemp(dir=env.srcrepo) except AttributeError as e1: raise TaskError( 'Attribute type error, expected String, Error: %s' % e1) except OSError as e2: raise TaskError('Could not create temporary file, Error: %s' % e2) env.run(['git', 'init'], directory=tempdir) env.run( ['git', 'remote', 'add', 'origin', self.attribute('url').value], directory=tempdir) if self.attribute('fetch_option').value is not '': env.run(['git', 'fetch', self.attribute('fetch_option').value], directory=tempdir) else: env.run(['git', 'fetch'], directory=tempdir) env.run(['git', 'checkout', self.attribute('revision').value], directory=tempdir) os.rename(tempdir, env.srcdir)
def threat_patch(self, env, patchStr): """ Applies a patch, or a series of patches, over the source code. """ hasPatch = env.check_program('patch') if hasPatch == False: raise TaskError('Patch tool is not present and it is required for' ' applying: %s, in: %s' % (self.attribute('patch').value, env._module_name)) vectorPath = env.replace_variables(patchStr).split(';') for item in vectorPath: if not env.exist_file(item): raise TaskError('Patch file is not present! missing file:' ' %s, in: %s' % (item, env._module_name)) try: env._logger.commands.write('cd ' + env.srcdir + '; patch -p1 < ' + item + '\n') status = getstatusoutput('cd ' + env.srcdir + '; patch -p1 < ' + item) except: raise TaskError('Patch error: %s, in: %s' % (item, env._module_name)) # if there were an error if status[0] != 0: if status[0] == 256: env._logger.commands.write(' > Patch problem: Ignoring' ' patch, either the patch file' ' does not exist or it was ' 'already applied!\n') else: raise TaskError('Patch error %s: %s, in: %s' % (status[0], item, env._module_name))
def build(self, env, jobs): """ Specific build implementation method. In order: 1. It apply possible patches, 2. Call make configure, if the configurations are available, 3. Call make with the set build arguments 4. Call make with the install arguments. """ if self.attribute('patch').value != '': self.threat_patch(env) # if the object directory does not exist, it should create it, to # avoid build error, since the make does not create the directory # it also makes it orthogonal to waf, that creates the target object dir try: env.run(['mkdir', env.objdir], directory=env.srcdir) except TaskError as e: # assume that if an error is thrown is because the directory already # exist, otherwise re-propagates the error if not "error 1" in e._reason: raise TaskError(e._reason) # Configures make, if there is a configuration argument that was passed as parameter options = [] if self.attribute('configure_arguments').value != '': options = bake.Utils.split_args( env.replace_variables( self.attribute('configure_arguments').value)) env.run(['make'] + self._flags() + options, directory=env.srcdir) jobsrt = [] if not jobs == -1: jobsrt = ['-j', str(jobs)] options = bake.Utils.split_args( env.replace_variables(self.attribute('build_arguments').value)) env.run(['make'] + jobsrt + self._flags() + options, directory=env.srcdir) if self.attribute('no_installation').value != str(True): sudoOp = [] if (env.sudoEnabled): sudoOp = ['sudo'] try: options = bake.Utils.split_args( env.replace_variables( self.attribute('install_arguments').value)) env.run(sudoOp + ['make', 'install'] + self._flags() + options, directory=env.srcdir) except TaskError as e: raise TaskError( ' Could not install, probably you do not have permission to' ' install %s: Verify if you have the required rights. Original' ' message: %s' % (env._module_name, e._reason))
def _decompress(self, filename, env): """Uses the appropriate tool to uncompress the sources.""" import tempfile import os tempdir = tempfile.mkdtemp(dir=env.srcrepo) extensions = [ ['tar', ['tar', 'xf']], ['tar.gz', ['tar', 'zxf']], ['tar.Z', ['tar', 'zxf']], ['tar.bz2', ['tar', 'jxf']], ['zip', ['unzip']], ['rar', ['unrar', 'e']], ['xz', ['unxz']], ['tar.xz', ['tar', 'Jxf']], ['7z', ['7z', 'x']], ['tgz', ['tar', 'xzvf']], ['tbz2', ['tar', 'jxf']] ] # finds the right tool for extension, command in extensions: if filename.endswith(extension): env.run(command + [filename], directory=tempdir) if self.attribute('extract_directory').value is not None: actual_extract_dir = self.attribute('extract_directory').value else: actual_extract_dir = os.path.basename(filename)[0:-len(extension) - 1] # finally, rename the extraction directory to the target # directory name. try: destDir=os.path.join(tempdir, actual_extract_dir) if os.path.isdir(env.srcdir): bake.Utils.mergeDirs(destDir, env.srcdir) else: os.rename(destDir, env.srcdir) shutil.rmtree(tempdir) # delete directory except (OSError, IOError) as e: raise TaskError("Rename problem for module: %s, from: %s, " "to: %s, Error: %s" % (env._module_name,os.path.join(tempdir, actual_extract_dir), env.srcdir, e)) return raise TaskError('Unknown Archive Type: %s, for module: %s' % (filename, env._module_name))
def run(self, args, directory=None, env=dict(), interactive=False): '''Executes a system program adding the libraries and over the correct directories. ''' if not interactive: env_string = '' if len(env) != 0: env_string = ' '.join([a + '=' + b for a, b in env.items()]) try: args_string = ' '.join(args) except TypeError as e: raise TaskError('Wrong argument type: %s, expected string,' ' error: %s' % (str(args), e)) self._logger.commands.write(env_string + ' ' + args_string + ' dir=' + str(directory) + '\n') stdin = None stdout = self._logger.stdout stderr = self._logger.stderr else: stdin = sys.stdin stdout = sys.stdout stderr = sys.stderr tmp = dict(list(os.environ.items()) + list(env.items())) # sets the library and binary paths tmp = self.append_to_path(tmp) # Calls the third party executable with the whole context try: popen = subprocess.Popen(args, stdin=stdin, stdout=stdout, stderr=stderr, cwd=directory, env=tmp) except Exception as e: raise TaskError( 'could not execute: %s %s. \nUnexpected error: %s' % (str(directory), str(args), str(e))) # Waits for the full execution of the third party software retcode = popen.wait() if retcode != 0: raise TaskError('Subprocess failed with error %d: %s' % (retcode, str(args)))
def update(self, env): """ Main update function. """ try: self._do_update(env, self._source, self._name) self.printResult(env, " Update ", self.OK) return True except TaskError as e: self.printResult(env, " Update ", self.FAIL) env._logger.commands.write(e.reason + '\n') if env.debug: import bake.Utils bake.Utils.print_backtrace() if env.stopOnErrorEnabled: self.handleStopOnError(e) return False except: self.printResult(env, " Update ", self.FAIL) env._logger.commands.write(e.reason + '\n') if env.debug: import bake.Utils bake.Utils.print_backtrace() if env.stopOnErrorEnabled: er = sys.exc_info()[1] self.handleStopOnError(TaskError('Error: %s' % (er))) return False
def build(self, env, jobs): """ Specific build implementation method. In order: 1. Call cmake to create the make files 2. Call make to build the code, 3. Call make with the set build arguments 4. Call make with the install parameters. """ options = [] if self.attribute('cmake_arguments').value != '': options = bake.Utils.split_args( env.replace_variables(self.attribute('cmake_arguments').value)) # if the object directory does not exist, it should create it, to # avoid build error, since the cmake does not create the directory # it also makes it orthogonal to waf, that creates the target object dir try: env.run(['mkdir', env.objdir], directory=env.srcdir) except TaskError as e: # assume that if an error is thrown is because the directory already # exist, otherwise re-propagates the error if not "error 1" in e._reason: raise TaskError(e._reason) jobsrt = [] if not jobs == -1: jobsrt = ['-j', str(jobs)] env.run([ 'cmake', env.srcdir, '-DCMAKE_INSTALL_PREFIX:PATH=' + env.installdir ] + self._variables() + options, directory=env.objdir) env.run(['make'] + jobsrt, directory=env.objdir) if self.attribute('build_arguments').value != '': env.run(['make'] + bake.Utils.split_args( env.replace_variables( self.attribute('build_arguments').value)), directory=env.objdir) if self.attribute('no_installation').value != True: sudoOp = [] if (env.sudoEnabled): sudoOp = ['sudo'] try: options = bake.Utils.split_args( env.replace_variables( self.attribute('install_arguments').value)) env.run(sudoOp + ['make', 'install'] + options, directory=env.objdir) except TaskError as e: print( ' Could not install, probably you do not have permission to' ' install %s: Verify if you have the required rights. Original' ' message: %s' % (env._module_name, e._reason))
def write(self): """ Creates the target configuration XML file.""" et = self.defineXml() try: et.write(self._bakefile) except IOError as e: raise TaskError('Problems writing the file, error: %s' % e)
def srcdir(self): ''' Returns the directory where Bake stores the source of the present module. ''' try: return os.path.join(self._sourcedir, self._module_directory()) except AttributeError as e: raise TaskError('Missing configuration: sourcedir= %s, ' 'module_directory= %s, Error: %s' % (self._sourcedir, self._module_directory(), e))
def test_print_backtrace(self): """Tests the _print_backtrace method from Util. """ testResult = bake.Utils.print_backtrace() self.assertTrue(testResult) try: raise TaskError('Process test failure') except TaskError as e: testResult = bake.Utils.print_backtrace() self.assertTrue('Process test failure' in testResult)
def download(self, env): """Downloads the specific file.""" url_local = self.attribute('url').value filename = os.path.basename(urlparse(url_local).path) tmpfile = os.path.join(env.srcrepo, filename) try: urlretrieve(url_local, filename=tmpfile) except IOError as e: raise TaskError( 'Download problem for module: %s, URL: %s, Error: %s' % (env._module_name, self.attribute('url').value, e)) self._decompress(tmpfile, env)
def objdir(self): ''' Returns the directory where Bake stores the object code of the present module. ''' if not self._module_supports_objdir: obj = self.srcdir else: try: obj = os.path.join(self.srcdir, self._objdir) except AttributeError as e: raise TaskError('Missing configuration: sourcedir= %s, ' 'objdir= %s, Error: %s' % (self._sourcedir, self._module_directory(), e)) return obj
def download(self, env, forceDownload): """ General download function. """ if self._build.attribute('supported_os').value : if not self._build.check_os(self._build.attribute('supported_os').value) : import platform import distro osName = platform.system().lower() (distname,version,ids)=distro.linux_distribution() print(' Downloading, but this module works only on \"%s\"' ' platform(s), %s is not supported for %s %s %s %s' % (self._build.attribute('supported_os').value, self._name, platform.system(), distname,version,ids)) try: self._do_download(env, self._source, self._name, forceDownload) if isinstance(self._source, SystemDependency): self.printResult(env, "Dependency ", self.OK) else: self.printResult(env, "Download", self.OK) return True except TaskError as e: if isinstance(self._source, SystemDependency): self.printResult(env, "Dependency ", self.FAIL) else: self.printResult(env, "Download", self.FAIL) env._logger.commands.write(e.reason+'\n') if env.debug : import bake.Utils bake.Utils.print_backtrace() if env.stopOnErrorEnabled: self.handleStopOnError(e) return False except: if isinstance(self._source, SystemDependency): self.printResult(env, "Install", self.FAIL) else: self.printResult(env, "Download", self.FAIL) if env.debug : import bake.Utils bake.Utils.print_backtrace() if env.stopOnErrorEnabled: er = sys.exc_info()[1] self.handleStopOnError(TaskError('Error: %s' % (er))) return False
def read(self): """ Reads the XML customized configuration file.""" try: et = ET.parse(self._bakefile) except IOError as e: err = re.sub(r'\[\w+ \w+\]+', ' ', str(e)).strip() raise TaskError( '>> Problems reading the configuration file, verify if' ' it exists or try calling bake.py configure. \n' ' Error: %s' % err) self._read_metadata(et) root = et.getroot() self._installdir = root.get('installdir') self._objdir = root.get('objdir') self._sourcedir = root.get('sourcedir') self._relative_directory_root = root.get('relative_directory_root') original_bakefile = root.get('bakefile') metadata = root.find('metadata') if metadata is not None: self._metadata_file = MetadataFile(metadata.get('filename'), h=metadata.get('hash')) # read which modules are enabled modules = root.findall('enabled') for module in modules: self._configured.append(self.lookup(module.get('name'))) enabled = self.lookup(module.get('name')) self.enable(enabled) # read which modules are disabled modules = root.findall('disabled') for module in modules: disabled = self.lookup(module.get('name')) self.disable(disabled) if metadata is not None: return self._metadata_file.is_hash_ok( ) #and original_bakefile == self._bakefile else: return True
def check_version(self, env): """Verifies if the right program exists in the system to handle the given compressed source file. """ # # distributions = [ # ['debian', 'apt-get'], # ['ubuntu', 'apt-get'], # ['fedora', 'yum'], # ['redhat', 'yum'], # ['centos', 'yum'], # ['suse', 'yast'], # ['darwin', 'port'], # ] # # import platform osName = platform.system().lower() if (not osName.startswith('linux') and not osName.startswith('darwin')): raise TaskError( "This installation model works only on Linux/Mac OS" " platforms, %s not supported for %s, %s" % (osName, env._module_name, self.attribute('error_message').value)) # (distribution, version, version_id) = platform.linux_distribution() # if not distribution: # distribution = 'darwin' # osName # else: # distribution = distribution.lower() program = self.source_systemtool() if not program == '': return env.check_program(program) # for dist, program in distributions: # if distribution.startswith(dist): # return env.check_program(program) return False
def clean(self, env): """ Main cleaning build option handler. """ srcDirTmp = self._name if self._source.attribute('module_directory').value : srcDirTmp = self._source.attribute('module_directory').value env.start_build(self._name, srcDirTmp, self._build.supports_objdir) if not os.path.isdir(env.objdir) or not os.path.isdir(env.srcdir): env.end_build() return try: self._build.clean(env) env.end_build() self._built_once = False self.printResult(env, "Clean ", self.OK) return True except TaskError as e: self.printResult(env, "Clean ", self.FAIL) err = re.sub(r'\[\w+ \w+\]+', ' ', str(e)).strip() env._logger.commands.write(err+'\n') if env.debug : import bake.Utils bake.Utils.print_backtrace() if env.stopOnErrorEnabled: self.handleStopOnError(e) return False except: env.end_build() if env.debug : import bake.Utils bake.Utils.print_backtrace() if env.stopOnErrorEnabled: er = sys.exc_info()[1] self.handleStopOnError(TaskError('Error: %s' % (er))) return False
def download(self, env): """ Verifies if the system dependency exists, if exists returns true, if not, and we are in a supported machine, tries to download and install the dependency. """ selfInstalation = self.attribute('try_to_install').value if selfInstalation: selfInstalation = selfInstalation.lower() if not selfInstalation == 'true' : raise TaskError(' Module: \"%s\" is required by other modules but it is not available on your system.\n' ' Ask your system admin or review your library database to add \"%s\"\n' ' More information from the module: \"%s\"' % (env._module_name, env._module_name, self.attribute('more_information').value)) # even if should try to install, if it is not a supported machine # we will not be able to osName = platform.system().lower().strip() if((osName.startswith('linux') or osName.startswith('darwin')) and selfInstalation == 'true'): (distribution, version, version_id) = platform.linux_distribution() if not distribution: distribution = osName.split()[0] # osName else: distribution = distribution.lower() command = self._get_command(distribution) # didn't recognize the distribution, asks user to install by himself if command == '' : raise TaskError(' Module: \"%s\" is required by other modules but it is not available on your system.\n' ' Ask your system admin\n' ' > More information from the module: \"%s\"' % (env._module_name, self.attribute('more_information').value)) installerName = self.attribute('name_' + command.split()[0]).value # if didn't find the specific installer name uses the default one if(not installerName): installerName = env._module_name if(not command): selfInstalation = 'false' else : selfInstalation = 'false' if not env._sudoEnabled : raise TaskError(' Module: \"%s\" is required by other modules and is not available on your system.\n' ' Ask your system admin to install it.\n' ' > More information from the module: \"%s\"' % (env._module_name, self.attribute('more_information').value)) errorTmp = None sudoer=self.attribute('sudoer_install').value if selfInstalation=='true': # Try to install if possible # if should try to install as sudoer if sudoer: sudoer = sudoer.lower() if(sudoer=='true' and (not env.sudoEnabled)): raise TaskError(' Module: \"%s\" requires sudo rights, if' ' you have the right, call bake with the' ' --sudo option, or ask your system admin' ' to install \"%s\" in your machine.\n' ' > More information from the module: \"%s\"' % (env._module_name, installerName, self.attribute('more_information').value)) # if the user asked to install everything as sudoer... do it! if(env.sudoEnabled): command = "sudo "+ command command = command try: env.run((command + installerName).split(" "), directory=env.srcrepo) return True except IOError as e: errorTmp = (' Self installation problem for module: \"%s\", ' 'Error: %s' % (env._module_name, e)) except TaskError as e1: if(env.sudoEnabled): e1.reason = (" Self installation problem for module: \"%s\", " "\n Probably either you miss sudo rights or the module is" " not present on your package management databases." "\n Try to either talk to your system admin or review your " "library database to add \"%s\"\n" " > More information from the module: \"%s\"" % (env._module_name, installerName, self.attribute('more_information').value)) else: e1.reason = (" Self installation problem for module: \"%s\", " "\n Probably either you need super user rights to install the packet," "or that the module is" " not present on your package management databases." "\n Try calling bake with the --sudo option and/or " "review your library database to add \"%s\"\n" " > More information from the module: \"%s\"" % (env._module_name, installerName, self.attribute('more_information').value)) raise e1 return True
def remove(self, env): """ Removes the the present version of the dependency.""" import platform # if the download is dependent of the machine's architecture osName = platform.system().lower() if(not osName.startswith('linux') and not osName.startswith('darwin')): raise TaskError("Not a Linux/Mac OS machine, self installation is not" " possible in %s for module: %s, %s" % (osName, env._module_name, self.attribute('error_message').value)) (distribution, version, version_id) = platform.linux_distribution() if not distribution: distribution = 'darwin' # osName else: distribution = distribution.lower() command = self._get_command(distribution) command = command.rstrip().rsplit(' ', 1)[0] + ' remove' installerName = self.attribute('name_' + command.split()[0]).value # if didn't find the specific installer name uses the default one if(not installerName): installerName = env._module_name # if should try to remove as sudoer sudoer=self.attribute('sudoer_install').value if sudoer: sudoer = sudoer.lower() if(sudoer =='true' and (not env.sudoEnabled)): raise TaskError(' Module: \"%s\" requires sudo rights, ask your' ' system admin to remove \"%s\" from your machine.\n' ' More information from the module: \"%s\"' % (env._module_name, installerName, self.attribute('more_information').value)) if(env.sudoEnabled): command = "sudo "+ command command = command # uses apt-get/yum/... to remove the module try: env.run((command + " " + installerName).split(" "), directory=env.srcrepo) except IOError as e: raise TaskError(' Removing module problem: \"%s\", Message: %s, Error: %s' % (env._module_name, self.attribute('more_information').value, e)) except TaskError as e1: if(env.sudoEnabled): e1.reason = (" Removing problem for module: \"%s\", " "\n Probably either you miss rights or the module is" " not present on your package management databases." "\n Try to either talk to your system admin or review your " "library database to add \"%s\"\n" " More information from the module: \"%s\"" % (env._module_name, installerName, self.attribute('more_information').value)) else: e1.reason = (" Removing problem for module: \"%s\", " "\n Probably you either need super user rights" " to remove the packet, or the module is" " not present on your package management databases." "\n Try calling bake with the --sudo option and/or " "review your library database to add \"%s\"\n" " More information from the module: \"%s\"" % (env._module_name, installerName, self.attribute('more_information').value)) raise TaskError(" Removing module problem: \"%s\",\n Probably you" "miss sudo rights or the module is not present on your package " "management databases. \n Try calling bake with --sudo or reviewing your" " library database to add \"%s\"\n" " More information from the module: \"%s\"" % (env._module_name, installerName, self.attribute('more_information').value)) return True
def build(self, env, jobs, force_clean): """ Main build function. """ # if there is no build we do not need to proceed if self._build.name() == 'none' or self._source.name( ) == 'system_dependency': srcDirTmp = self._name if self._source.attribute('module_directory').value: srcDirTmp = self._source.attribute('module_directory').value if self._build.attribute('pre_installation').value != '': self._build.perform_pre_installation(env) if self._build.attribute('patch').value != '': self._build.threat_patch(env, self._build.attribute('patch').value) if self._build.attribute('post_installation').value != '': self._build.perform_post_installation(env) self._build.threat_variables(env) return True # delete in case this is a new build configuration # and there are old files around if force_clean: self.uninstall(env) if not self._built_once: self.clean(env) srcDirTmp = self._name if self._source.attribute('module_directory').value: srcDirTmp = self._source.attribute('module_directory').value env.start_build(self._name, srcDirTmp, self._build.supports_objdir) # setup the monitor monitor = FilesystemMonitor(env.installdir) monitor.start() if self._build.attribute('supported_os').value: if not self._build.check_os( self._build.attribute('supported_os').value): import platform osName = platform.system().lower() (distname, version, ids) = platform.linux_distribution() self.printResult(env, "Building", self.FAIL) print(' This module works only on \"%s\"' ' platform(s), %s is not supported for %s %s %s %s' % (self._build.attribute('supported_os').value, self._name, platform.system(), distname, version, ids)) return if not os.path.isdir(env.installdir): os.mkdir(env.installdir) if self._build.supports_objdir and not os.path.isdir(env.objdir): os.mkdir(env.objdir) try: if not os.path.isdir(env.srcdir): raise TaskError( 'Source is not available for module %s: ' 'directory %s not found. Try %s download first.' % (env._module_name, env.srcdir, sys.argv[0])) if self._build.attribute('pre_installation').value != '': self._build.perform_pre_installation(env) self._build.threat_variables(env) if self._build.attribute('patch').value != '': self._build.threat_patch(env, self._build.attribute('patch').value) self._build.build(env, jobs) self._installed = monitor.end() if self._build.attribute('post_installation').value != '': self._build.perform_post_installation(env) env.end_build() self._built_once = True self.printResult(env, "Built", self.OK) return True except TaskError as e: self.printResult(env, "Building", self.FAIL) env._logger.commands.write(" > " + e.reason + '\n') if env.debug: import bake.Utils bake.Utils.print_backtrace() env.end_build() if env.stopOnErrorEnabled: self.handleStopOnError(e) return False except: self._installed = monitor.end() env.end_build() if env.debug: import bake.Utils bake.Utils.print_backtrace() if env.stopOnErrorEnabled: er = sys.exc_info()[1] self.handleStopOnError(TaskError('Error: %s' % (er))) return False