#!/usr/bin/python3 # -*- coding: utf-8 -*- from collections import OrderedDict import os import subprocess import sys DEFAULT_CONF_PATH = 'default-conf.sh' CONF_PATH = 'conf.sh' CONF = dict() def log(text, error=False): fo = sys.stderr if error else sys.stdout print(text, file=fo) fo.flush() def get_dir(file_path): return os.path.dirname(os.path.abspath(os.path.expanduser(file_path))) def exec_cmd(cmd, get_out=False): stdout = subprocess.PIPE if get_out else sys.stdout stderr = subprocess.PIPE if get_out else sys.stderr shell = not isinstance(cmd, (tuple, list)) p = subprocess.Popen(cmd, stdin=sys.stdin, stdout=stdout, stderr=stderr, shell=shell) out, err = p.communicate() if get_out: out = out.decode('utf-8').strip() if out else '' if err: if out: out += '\n' out += 'Stderr:\n' + err.decode('utf-8').strip() return p.returncode, out else: sys.stdout.flush() sys.stderr.flush() return p.returncode def load_conf(): base_dir = get_dir(__file__) files = ( (os.path.join(base_dir, DEFAULT_CONF_PATH), True), (os.path.join(base_dir, CONF_PATH), False), ) only_default = True override = OrderedDict() for path, is_default in files: if not os.path.exists(path): log('The configuration file for EnvSetup script does not exist.\nPath of configuration file: %s' % path, error=True) if is_default: return dict() # Load conf with open(path, 'r') as fo: content = fo.read() # Parse conf for line in content.split('\n'): line = line.strip() if line and not line.startswith('#') and '=' in line: name, *val = line.split('=') name = name.strip(' \t\'\"') val = ('='.join(val)).strip(' \t\'\"') CONF[name] = val if is_default: override[name] = False else: only_default = False override[name] = True CONF['_override'] = override # Check a value to know if the config file has been changed if only_default: log('\033[93mWarning:\033[0m') log('The configuration is using only default values.') log('Perhaps you forget to change the configuration.') log('Path of configuration file: %s' % os.path.join(base_dir, CONF_PATH)) log('Perhaps you want to quit this script to change the configuration?\n') return CONF def get_conf(name, default=None): if not CONF: load_conf() return CONF.get(name, default) def run_commands(cmds): # run a serie of successive commands try: # Execute commands for cmd in cmds: if not isinstance(cmd, dict): cmd = dict(line=cmd) if cmd.get('cond'): cond = cmd['cond'] negate = cmd.get('cond_neg') skip = cmd.get('cond_skip') code = exec_cmd(cond) success = code != 0 if negate else code == 0 if not success: msg = 'Condition for command "%s" not fullfilled.' % cmd['line'] if skip: log('%s Command skipped.' % msg) continue raise Exception(msg) if cmd['line'] == 'write': if not cmd.get('target'): raise Exception('No target file to write in.') if cmd.get('backup') and os.path.exists(cmd['target']) and not os.path.exists(cmd['target'] + '.back'): os.rename(cmd['target'], cmd['target'] + '.back') log('A backup file has been created for:\n%s' % cmd['target']) # Load content from template if any content = cmd.get('content', '') if cmd.get('template'): if not os.path.exists(cmd['template']): raise Exception('Template file does not exist: %s.' % cmd['template']) with open(cmd['template'], 'r') as fd: content = fd.read() if cmd.get('params'): for k, v in cmd['params']: content = content.replace(k, v) # Write target file with open(cmd['target'], 'w+') as fd: fd.write(content) log('File %s written' % cmd['target']) elif cmd['line'] == 'backup': if not cmd.get('target'): raise Exception('No target file to backup.') if not os.path.exists(cmd['target'] + '.back'): os.rename(cmd['target'], cmd['target'] + '.back') log('A backup file has been created for:\n%s' % cmd['target']) else: log('A backup file already exist for:\n%s' % cmd['target']) else: log('>>> ' + cmd['line']) code = exec_cmd(cmd['line']) if code != 0: raise Exception('Command exited with code %s.' % code) except Exception as e: log('Command failed:\n%s' % e) raise