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
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
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())
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
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())
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())
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)
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))
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 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
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)
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