Beispiel #1
0
def load_config(confpath, dotpath, profile):
    '''Load the config file from path'''
    conf = Cfg(confpath, dotpath)
    opts = conf.get_configs()
    opts['dry'] = False
    opts['profile'] = profile
    opts['safe'] = True
    opts['installdiff'] = True
    return conf, opts
Beispiel #2
0
def load_config(confpath, profile):
    '''Load the config file from path'''
    conf = Cfg(confpath)
    opts = conf.get_configs()
    opts['dry'] = False
    opts['profile'] = profile
    opts['safe'] = True
    opts['installdiff'] = True
    opts['link'] = False
    opts['quiet'] = True
    opts['dopts'] = ''
    return conf, opts
Beispiel #3
0
def load_config(confpath, profile):
    '''Load the config file from path'''
    conf = Cfg(confpath)
    opts = conf.get_settings()
    opts['dry'] = False
    opts['profile'] = profile
    opts['safe'] = True
    opts['installdiff'] = True
    opts['link'] = False
    opts['debug'] = True
    opts['dopts'] = ''
    return conf, opts
def main():
    args = docopt(USAGE)
    path = os.path.expanduser(args['<config.yaml>'])

    try:

        conf = Cfg(path)
    except ValueError as e:
        print('error: {}'.format(str(e)))
        return False

    conf.short_to_long()
    print(conf.dump())
Beispiel #5
0
def load_config(confpath, profile):
    """Load the config file from path"""
    conf = Cfg(confpath)
    opts = conf.get_settings()
    opts['dry'] = False
    opts['profile'] = profile
    opts['safe'] = True
    opts['installdiff'] = True
    opts['link'] = LinkTypes.NOLINK.value
    opts['showdiff'] = True
    opts['debug'] = True
    opts['dopts'] = ''
    opts['variables'] = {}
    return conf, opts
Beispiel #6
0
    def test_config(self):
        '''Test the config class'''
        tmp = get_tempfolder()
        self.assertTrue(os.path.exists(tmp))
        self.addCleanup(clean, tmp)

        confpath = create_fake_config(tmp,
                                      configname=self.CONFIG_NAME,
                                      dotpath=self.CONFIG_DOTPATH,
                                      backup=self.CONFIG_BACKUP,
                                      create=self.CONFIG_CREATE)
        conf = Cfg(confpath)
        self.assertTrue(conf is not None)

        opts = conf.get_configs()
        self.assertTrue(opts is not None)
        self.assertTrue(opts != {})
        self.assertTrue(opts['backup'] == self.CONFIG_BACKUP)
        self.assertTrue(opts['create'] == self.CONFIG_CREATE)
        dotpath = os.path.join(tmp, self.CONFIG_DOTPATH)
        self.assertTrue(opts['dotpath'] == dotpath)
        self.assertTrue(conf._is_valid())
Beispiel #7
0
    def test_config(self):
        '''Test the config class'''
        tmp = get_tempfolder()
        self.assertTrue(os.path.exists(tmp))
        self.addCleanup(clean, tmp)

        confpath = create_fake_config(tmp,
                                      configname=self.CONFIG_NAME,
                                      dotpath=self.CONFIG_DOTPATH,
                                      backup=self.CONFIG_BACKUP,
                                      create=self.CONFIG_CREATE)
        conf = Cfg(confpath)
        self.assertTrue(conf is not None)

        opts = conf.get_configs()
        self.assertTrue(opts is not None)
        self.assertTrue(opts != {})
        self.assertTrue(opts['backup'] == self.CONFIG_BACKUP)
        self.assertTrue(opts['create'] == self.CONFIG_CREATE)
        dotpath = os.path.join(tmp, self.CONFIG_DOTPATH)
        self.assertTrue(opts['dotpath'] == dotpath)
        self.assertTrue(conf._is_valid())
        self.assertTrue(conf.dump() != '')
    def test_install(self):
        """Test the install function"""

        # dotpath location
        tmp = get_tempdir()
        self.assertTrue(os.path.exists(tmp))
        self.addCleanup(clean, tmp)

        # where dotfiles will be installed
        dst = get_tempdir()
        self.assertTrue(os.path.exists(dst))
        self.addCleanup(clean, dst)

        # create the dotfile in dotdrop
        f1, c1 = create_random_file(tmp)
        dst1 = os.path.join(dst, get_string(6))
        d1 = Dotfile(get_string(5), dst1, os.path.basename(f1))
        # fake a print
        self.assertTrue(str(d1) != '')
        f2, c2 = create_random_file(tmp)
        dst2 = os.path.join(dst, get_string(6))
        d2 = Dotfile(get_string(5), dst2, os.path.basename(f2))
        with open(f2, 'w') as f:
            f.write(self.TEMPLATE)
        f3, _ = create_random_file(tmp, binary=True)
        dst3 = os.path.join(dst, get_string(6))
        d3 = Dotfile(get_string(5), dst3, os.path.basename(f3))

        # create a directory dotfile
        dir1 = os.path.join(tmp, 'somedir')
        create_dir(dir1)
        fd, _ = create_random_file(dir1)
        dstd = os.path.join(dst, get_string(6))
        ddot = Dotfile(get_string(5), dstd, os.path.basename(dir1))

        # to test backup
        f4, c4 = create_random_file(tmp)
        dst4 = os.path.join(dst, get_string(6))
        d4 = Dotfile(key=get_string(6), dst=dst4, src=os.path.basename(f4))
        with open(dst4, 'w') as f:
            f.write(get_string(16))

        # to test link
        f5, c5 = create_random_file(tmp)
        dst5 = os.path.join(dst, get_string(6))
        self.addCleanup(clean, dst5)
        d5 = Dotfile(get_string(6), dst5, os.path.basename(f5), link=True)

        # create the dotfile directories in dotdrop
        dir1 = create_dir(os.path.join(tmp, get_string(6)))
        self.assertTrue(os.path.exists(dir1))
        self.addCleanup(clean, dir1)
        dst6 = os.path.join(dst, get_string(6))
        # fill with files
        sub1, _ = create_random_file(dir1, template=True)
        self.assertTrue(os.path.exists(sub1))
        sub2, _ = create_random_file(dir1)
        self.assertTrue(os.path.exists(sub2))
        # make up the dotfile
        d6 = Dotfile(get_string(6), dst6, os.path.basename(dir1))

        # to test symlink directories
        dir2 = create_dir(os.path.join(tmp, get_string(6)))
        self.assertTrue(os.path.exists(dir2))
        self.addCleanup(clean, dir2)
        dst7 = os.path.join(dst, get_string(6))
        # fill with files
        sub3, _ = create_random_file(dir2)
        self.assertTrue(os.path.exists(sub3))
        sub4, _ = create_random_file(dir2)
        self.assertTrue(os.path.exists(sub4))
        # make up the dotfile
        d7 = Dotfile(get_string(6), dst7, os.path.basename(dir2), link=True)

        # to test actions
        value = get_string(12)
        fact = '/tmp/action'
        self.addCleanup(clean, fact)
        act1 = Action('testaction', 'post',
                      'echo "{}" > {}'.format(value, fact))
        f8, c8 = create_random_file(tmp)
        dst8 = os.path.join(dst, get_string(6))
        d8 = Dotfile(get_string(6), dst8, os.path.basename(f8), actions=[act1])

        # to test transformations
        trans1 = 'trans1'
        trans2 = 'trans2'
        cmd = 'cat {0} | sed \'s/%s/%s/g\' > {1}' % (trans1, trans2)
        tr = Action('testtrans', 'post', cmd)
        f9, c9 = create_random_file(tmp, content=trans1)
        dst9 = os.path.join(dst, get_string(6))
        d9 = Dotfile(get_string(6), dst9, os.path.basename(f9), trans_r=tr)

        # to test template
        f10, _ = create_random_file(tmp, content='{{@@ header() @@}}')
        dst10 = os.path.join(dst, get_string(6))
        d10 = Dotfile(get_string(6), dst10, os.path.basename(f10))

        # generate the config and stuff
        profile = get_string(5)
        confpath = os.path.join(tmp, self.CONFIG_NAME)
        dotfiles = [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, ddot]
        self.fake_config(confpath, dotfiles, profile, tmp, [act1], [tr])
        conf = Cfg(confpath)
        self.assertTrue(conf is not None)

        # install them
        conf, opts = load_config(confpath, profile)
        opts['safe'] = False
        opts['debug'] = True
        opts['showdiff'] = True
        opts['variables'] = {}
        cmd_install(opts, conf)

        # now compare the generated files
        self.assertTrue(os.path.exists(dst1))
        self.assertTrue(os.path.exists(dst2))
        self.assertTrue(os.path.exists(dst3))
        self.assertTrue(os.path.exists(dst5))
        self.assertTrue(os.path.exists(dst6))
        self.assertTrue(os.path.exists(dst7))
        self.assertTrue(os.path.exists(dst8))
        self.assertTrue(os.path.exists(dst10))
        self.assertTrue(os.path.exists(fd))

        # check if 'dst5' is a link whose target is 'f5'
        self.assertTrue(os.path.islink(dst5))
        self.assertTrue(os.path.realpath(dst5) == os.path.realpath(f5))

        # check if 'dst7' is a link whose target is 'dir2'
        self.assertTrue(os.path.islink(dst7))
        self.assertTrue(os.path.realpath(dst7) == os.path.realpath(dir2))

        # make sure backup is there
        b = dst4 + Installer.BACKUP_SUFFIX
        self.assertTrue(os.path.exists(b))

        self.assertTrue(filecmp.cmp(f1, dst1, shallow=True))
        f2content = open(dst2, 'r').read()
        self.assertTrue(f2content == self.RESULT)
        self.assertTrue(filecmp.cmp(f3, dst3, shallow=True))

        # test action has been executed
        self.assertTrue(os.path.exists(fact))
        self.assertTrue(str(act1) != '')
        actcontent = open(fact, 'r').read().rstrip()
        self.assertTrue(actcontent == value)

        # test transformation has been done
        self.assertTrue(os.path.exists(dst9))
        transcontent = open(dst9, 'r').read().rstrip()
        self.assertTrue(transcontent == trans2)

        # test template has been remplaced
        self.assertTrue(os.path.exists(dst10))
        tempcontent = open(dst10, 'r').read().rstrip()
        self.assertTrue(tempcontent == header())
Beispiel #9
0
    def test_include(self):
        tmp = get_tempfolder()
        self.assertTrue(os.path.exists(tmp))
        self.addCleanup(clean, tmp)

        # create a base config file
        confpath = create_fake_config(tmp,
                                      configname=self.CONFIG_NAME,
                                      dotpath=self.CONFIG_DOTPATH,
                                      backup=self.CONFIG_BACKUP,
                                      create=self.CONFIG_CREATE)

        # edit the config
        with open(confpath, 'r') as f:
            content = yaml.load(f)

        # adding dotfiles
        df1key = 'f_vimrc'
        df2key = 'f_xinitrc'
        content['dotfiles'] = {
            df1key: {
                'dst': '~/.vimrc',
                'src': 'vimrc'
            },
            df2key: {
                'dst': '~/.xinitrc',
                'src': 'xinitrc'
            }
        }

        # adding profiles
        pf1key = 'host1'
        pf2key = 'host2'
        content['profiles'] = {
            pf1key: {
                'dotfiles': [df2key],
                'include': ['host2']
            },
            pf2key: {
                'dotfiles': [df1key]
            }
        }

        # save the new config
        with open(confpath, 'w') as f:
            yaml.dump(content, f, default_flow_style=False, indent=2)

        # do the tests
        conf = Cfg(confpath)
        self.assertTrue(conf is not None)

        # test profile
        opts = conf.get_configs()
        print(conf.get_profiles())
        profiles = conf.get_profiles()
        self.assertTrue(pf1key in profiles)
        self.assertTrue(pf2key in profiles)

        # test dotfiles
        dotfiles = conf.get_dotfiles(pf1key)
        self.assertTrue(df1key in [x.key for x in dotfiles])
        self.assertTrue(df2key in [x.key for x in dotfiles])
        dotfiles = conf.get_dotfiles(pf2key)
        self.assertTrue(df1key in [x.key for x in dotfiles])
        self.assertFalse(df2key in [x.key for x in dotfiles])

        # test not existing included profile
        # edit the config
        with open(confpath, 'r') as f:
            content = yaml.load(f)
        content['profiles'] = {
            pf1key: {
                'dotfiles': [df2key],
                'include': ['host2']
            },
            pf2key: {
                'dotfiles': [df1key],
                'include': ['host3']
            }
        }

        # save the new config
        with open(confpath, 'w') as f:
            yaml.dump(content, f, default_flow_style=False, indent=2)

        # do the tests
        conf = Cfg(confpath)
        self.assertTrue(conf is not None)
Beispiel #10
0
class Options(AttrMonitor):
    def __init__(self, args=None):
        """constructor
        @args: argument dictionary (if None use sys)
        """
        self.args = args
        if not args:
            self.args = docopt(USAGE, version=VERSION)
        self.log = Logger()
        self.debug = self.args['--verbose']
        if not self.debug and ENV_DEBUG in os.environ:
            self.debug = True
        if ENV_NODEBUG in os.environ:
            self.debug = False
        self.profile = self.args['--profile']
        self.confpath = os.path.expanduser(self.args['--cfg'])
        if self.debug:
            self.log.dbg('config file: {}'.format(self.confpath))

        self._read_config(self.profile)
        self._apply_args()
        self._fill_attr()
        if ENV_NOBANNER not in os.environ \
           and self.banner \
           and not self.args['--no-banner']:
            self._header()
        self._print_attr()
        # start monitoring for bad attribute
        self._set_attr_err = True

    def _header(self):
        """print the header"""
        self.log.log(BANNER)
        self.log.log('')

    def _read_config(self, profile=None):
        """read the config file"""
        self.conf = Cfg(self.confpath, profile=profile, debug=self.debug)
        # transform the configs in attribute
        for k, v in self.conf.get_settings().items():
            setattr(self, k, v)

    def _apply_args(self):
        """apply cli args as attribute"""
        # the commands
        self.cmd_list = self.args['list']
        self.cmd_listfiles = self.args['listfiles']
        self.cmd_install = self.args['install']
        self.cmd_compare = self.args['compare']
        self.cmd_import = self.args['import']
        self.cmd_update = self.args['update']
        self.cmd_detail = self.args['detail']

        # adapt attributes based on arguments
        self.dry = self.args['--dry']
        self.safe = not self.args['--force']
        self.link = LinkTypes.NOLINK
        if self.link_by_default:
            self.link = LinkTypes.PARENTS

        if self.args['--inv-link']:
            # Only invert link type from NOLINK to PARENTS and vice-versa
            if self.link == LinkTypes.NOLINK:
                self.link = LinkTypes.PARENTS
            elif self.link == LinkTypes.PARENTS:
                self.link = LinkTypes.NOLINK

        # "listfiles" specifics
        self.listfiles_templateonly = self.args['--template']
        # "install" specifics
        self.install_temporary = self.args['--temp']
        self.install_keys = self.args['<key>']
        self.install_diff = not self.args['--nodiff']
        self.install_showdiff = self.showdiff or self.args['--showdiff']
        self.install_backup_suffix = BACKUP_SUFFIX
        # "compare" specifics
        self.compare_dopts = self.args['--dopts']
        self.compare_focus = self.args['--file']
        self.compare_ignore = self.args['--ignore']
        self.compare_ignore.append('*{}'.format(self.install_backup_suffix))
        # "import" specifics
        self.import_path = self.args['<path>']
        # "update" specifics
        self.update_path = self.args['<path>']
        self.update_iskey = self.args['--key']
        self.update_ignore = self.args['--ignore']
        self.update_ignore.append('*{}'.format(self.install_backup_suffix))
        self.update_showpatch = self.args['--show-patch']
        # "detail" specifics
        self.detail_keys = self.args['<key>']

    def _fill_attr(self):
        """create attributes from conf"""
        # variables
        self.variables = self.conf.get_variables(self.profile,
                                                 debug=self.debug).copy()
        # the dotfiles
        self.dotfiles = self.conf.eval_dotfiles(self.profile,
                                                self.variables,
                                                debug=self.debug).copy()
        # the profiles
        self.profiles = self.conf.get_profiles()

    def _print_attr(self):
        """print all of this class attributes"""
        if not self.debug:
            return
        self.log.dbg('options:')
        for att in dir(self):
            if att.startswith('_'):
                continue
            val = getattr(self, att)
            if callable(val):
                continue
            self.log.dbg('- {}: \"{}\"'.format(att, val))

    def _attr_set(self, attr):
        """error when some inexistent attr is set"""
        raise Exception('bad option: {}'.format(attr))
Beispiel #11
0
 def _read_config(self, profile=None):
     """read the config file"""
     self.conf = Cfg(self.confpath, profile=profile, debug=self.debug)
     # transform the configs in attribute
     for k, v in self.conf.get_settings().items():
         setattr(self, k, v)
Beispiel #12
0
def main():
    """entry point"""
    ret = True
    args = docopt(USAGE, version=VERSION)

    try:
        conf = Cfg(os.path.expanduser(args['--cfg']))
    except ValueError as e:
        LOG.err('Config format error: {}'.format(str(e)))
        return False

    opts = conf.get_settings()
    opts['dry'] = args['--dry']
    opts['profile'] = args['--profile']
    opts['safe'] = not args['--force']
    opts['installdiff'] = not args['--nodiff']
    opts['link'] = args['--link']
    opts['debug'] = args['--verbose']
    opts['variables'] = conf.get_variables()
    opts['showdiff'] = opts['showdiff'] or args['--showdiff']

    if opts['debug']:
        LOG.dbg('config file: {}'.format(args['--cfg']))
        LOG.dbg('opts: {}'.format(opts))

    # resolve dynamic paths
    conf.eval_dotfiles(opts['profile'], debug=opts['debug'])

    if ENV_NOBANNER not in os.environ \
            and opts['banner'] \
            and not args['--no-banner']:
        _header()

    try:

        if args['list']:
            # list existing profiles
            if opts['debug']:
                LOG.dbg('running cmd: list')
            cmd_list_profiles(conf)

        elif args['listfiles']:
            # list files for selected profile
            if opts['debug']:
                LOG.dbg('running cmd: listfiles')
            cmd_list_files(opts, conf, templateonly=args['--template'])

        elif args['install']:
            # install the dotfiles stored in dotdrop
            if opts['debug']:
                LOG.dbg('running cmd: install')
            ret = cmd_install(opts,
                              conf,
                              temporary=args['--temp'],
                              keys=args['<key>'])

        elif args['compare']:
            # compare local dotfiles with dotfiles stored in dotdrop
            if opts['debug']:
                LOG.dbg('running cmd: compare')
            tmp = get_tmpdir()
            opts['dopts'] = args['--dopts']
            ret = cmd_compare(opts,
                              conf,
                              tmp,
                              focus=args['--file'],
                              ignore=args['--ignore'])
            # clean tmp directory
            remove(tmp)

        elif args['import']:
            # import dotfile(s)
            if opts['debug']:
                LOG.dbg('running cmd: import')
            ret = cmd_importer(opts, conf, args['<path>'])

        elif args['update']:
            # update a dotfile
            if opts['debug']:
                LOG.dbg('running cmd: update')
            iskey = args['--key']
            ret = cmd_update(opts, conf, args['<path>'], iskey=iskey)

        elif args['detail']:
            # detail files
            if opts['debug']:
                LOG.dbg('running cmd: update')
            cmd_detail(opts, conf, keys=args['<key>'])

    except KeyboardInterrupt:
        LOG.err('interrupted')
        ret = False

    return ret
Beispiel #13
0
    def test_include(self):
        tmp = get_tempfolder()
        self.assertTrue(os.path.exists(tmp))
        self.addCleanup(clean, tmp)

        # create a base config file
        confpath = create_fake_config(tmp,
                                      configname=self.CONFIG_NAME,
                                      dotpath=self.CONFIG_DOTPATH,
                                      backup=self.CONFIG_BACKUP,
                                      create=self.CONFIG_CREATE)

        # edit the config
        with open(confpath, 'r') as f:
            content = yaml.load(f)

        # adding dotfiles
        df1key = 'f_vimrc'
        df2key = 'f_xinitrc'
        content['dotfiles'] = {
                df1key: {'dst': '~/.vimrc', 'src': 'vimrc'},
                df2key: {'dst': '~/.xinitrc', 'src': 'xinitrc'}
                }

        # adding profiles
        pf1key = 'host1'
        pf2key = 'host2'
        content['profiles'] = {
                pf1key: {'dotfiles': [df2key], 'include': ['host2']},
                pf2key: {'dotfiles': [df1key]}
                }

        # save the new config
        with open(confpath, 'w') as f:
            yaml.dump(content, f, default_flow_style=False, indent=2)

        # do the tests
        conf = Cfg(confpath)
        self.assertTrue(conf is not None)

        # test profile
        opts = conf.get_configs()
        print(conf.get_profiles())
        profiles = conf.get_profiles()
        self.assertTrue(pf1key in profiles)
        self.assertTrue(pf2key in profiles)

        # test dotfiles
        dotfiles = conf.get_dotfiles(pf1key)
        self.assertTrue(df1key in [x.key for x in dotfiles])
        self.assertTrue(df2key in [x.key for x in dotfiles])
        dotfiles = conf.get_dotfiles(pf2key)
        self.assertTrue(df1key in [x.key for x in dotfiles])
        self.assertFalse(df2key in [x.key for x in dotfiles])

        # test not existing included profile
        # edit the config
        with open(confpath, 'r') as f:
            content = yaml.load(f)
        content['profiles'] = {
                pf1key: {'dotfiles': [df2key], 'include': ['host2']},
                pf2key: {'dotfiles': [df1key], 'include': ['host3']}
                }

        # save the new config
        with open(confpath, 'w') as f:
            yaml.dump(content, f, default_flow_style=False, indent=2)

        # do the tests
        conf = Cfg(confpath)
        self.assertTrue(conf is not None)
Beispiel #14
0
def main():
    """entry point"""
    ret = True
    args = docopt(USAGE, version=VERSION)
    try:
        conf = Cfg(os.path.expanduser(args['--cfg']))
    except ValueError as e:
        LOG.err('error: {}'.format(str(e)))
        return False

    opts = conf.get_settings()
    opts['dry'] = args['--dry']
    opts['profile'] = args['--profile']
    opts['safe'] = not args['--force']
    opts['installdiff'] = not args['--nodiff']
    opts['link'] = args['--link']
    opts['debug'] = args['--verbose']

    if opts['debug']:
        LOG.dbg('config file: {}'.format(args['--cfg']))
        LOG.dbg('opts: {}'.format(opts))

    if opts['banner'] and not args['--no-banner']:
        header()

    try:

        if args['list']:
            # list existing profiles
            list_profiles(conf)

        elif args['listfiles']:
            # list files for selected profile
            list_files(opts, conf)

        elif args['install']:
            # install the dotfiles stored in dotdrop
            ret = install(opts, conf)

        elif args['compare']:
            # compare local dotfiles with dotfiles stored in dotdrop
            tmp = get_tmpdir()
            opts['dopts'] = args['--dopts']
            ret = compare(opts, conf, tmp, args['--files'], args['--ignore'])
            if os.listdir(tmp):
                LOG.raw('\ntemporary files available under {}'.format(tmp))
            else:
                os.rmdir(tmp)

        elif args['import']:
            # import dotfile(s)
            importer(opts, conf, args['<paths>'])

        elif args['update']:
            # update a dotfile
            update(opts, conf, args['<paths>'])

    except KeyboardInterrupt:
        LOG.err('interrupted')
        ret = False

    return ret