Skip to content
Snippets Groups Projects
utils.py 5.24 KiB
Newer Older
Stéphane Diemer's avatar
Stéphane Diemer committed
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from collections import OrderedDict
Stéphane Diemer's avatar
Stéphane Diemer committed
import os
import subprocess
import sys


DEFAULT_CONF_PATH = 'default-conf.sh'
CONF_PATH = 'conf.sh'
CONF = dict()
Stéphane Diemer's avatar
Stéphane Diemer committed


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__)
        (os.path.join(base_dir, DEFAULT_CONF_PATH), True),
        (os.path.join(base_dir, CONF_PATH), False),
    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)
        # 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
                    override[name] = 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')
Stéphane Diemer's avatar
Stéphane Diemer committed


def get_conf(name, default=None):
    if not CONF:
        load_conf()
    return CONF.get(name, default)
Stéphane Diemer's avatar
Stéphane Diemer committed


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