def test_activate_normal(self, tmp_path): fname = self.write_flist(tmp_path, 'file:cat1,cat2\nfile2:cat3\n') flist = Filelist(fname) assert flist.activate(['cat2']) == { 'file': { 'categories': ['cat1', 'cat2'], 'plugin': 'plain', }}
def test_activate_groups(self, tmp_path): fname = self.write_flist(tmp_path, 'group=cat1,cat2\nfile:cat1') flist = Filelist(fname) assert flist.activate(['group']) == { 'file': { 'categories': ['cat1'], 'plugin': 'plain' }}
def test_comments_and_empty(self, tmp_path): fname = self.write_flist(tmp_path, '# test comment\n '+ '\n # spaced comment\n') flist = Filelist(fname) assert flist.groups == {} assert flist.files == {}
def test_nocat_plugin(self, tmp_path): fname = self.write_flist(tmp_path, 'file|encrypt') flist = Filelist(fname) assert flist.files == { 'file': [{ 'categories': ['common'], 'plugin': 'encrypt' }]}
def test_common_file(self, tmp_path): fname = self.write_flist(tmp_path, 'common_file/with/path') flist = Filelist(fname) assert flist.groups == {} assert flist.files == {'common_file/with/path': [{ 'categories': ['common'], 'plugin': 'plain' }]}
def test_manifest(self, tmp_path): fname = self.write_flist(tmp_path, 'group=cat1,cat2\ncfile\nnfile:cat1,cat2\n' 'gfile:group\npfile:cat1,cat2|encrypt') flist = Filelist(fname) manifest = flist.manifest() assert type(manifest) is dict assert sorted(manifest) == sorted(['plain', 'encrypt']) assert sorted(manifest['plain']) == sorted(['common/cfile', 'cat1/nfile', 'cat2/nfile', 'cat1/gfile', 'cat2/gfile']) assert sorted(manifest['encrypt']) == sorted(['cat1/pfile', 'cat2/pfile'])
def test_group(self, tmp_path): # Test where group name != hostname fname = self.write_flist(tmp_path, 'group=cat1,cat2,cat3') flist = Filelist(fname) assert flist.groups == {'group': ['cat1', 'cat2', 'cat3']} assert flist.files == {} # Test where group name == hostname fname = self.write_flist(tmp_path, socket.gethostname() + '=cat1,cat2,cat3') flist = Filelist(fname) assert flist.groups == { socket.gethostname(): ['cat1', 'cat2', 'cat3', socket.gethostname()] } assert flist.files == {}
def test_file(self, tmp_path): fname = self.write_flist(tmp_path, 'file:cat1,cat2\nfile:cat3\n') flist = Filelist(fname) assert flist.groups == {} assert flist.files == { 'file': [{ 'categories': ['cat1', 'cat2'], 'plugin': 'plain' }, { 'categories': ['cat3'], 'plugin': 'plain' }]}
def test_mix(self, tmp_path): fname = self.write_flist(tmp_path, 'group=cat1,cat2\ncfile\n#comment\nnfile:cat1,cat2\n') flist = Filelist(fname) assert flist.groups == {'group': ['cat1', 'cat2']} assert flist.files == { 'cfile': [{ 'categories': ['common'], 'plugin': 'plain' }], 'nfile': [{ 'categories': ['cat1', 'cat2'], 'plugin': 'plain' }]}
def test_group(self, tmp_path): fname = self.write_flist(tmp_path, 'group=cat1,cat2,cat3') flist = Filelist(fname) assert flist.groups == {'group': ['cat1', 'cat2', 'cat3']} assert flist.files == {}
def test_activate_duplicate(self, tmp_path): fname = self.write_flist(tmp_path, 'file:cat1,cat2\nfile:cat2\n') flist = Filelist(fname) with pytest.raises(RuntimeError): flist.activate(['cat2'])
def main(args=None, cwd=os.getcwd(), home=info.home): if args is None: args = sys.argv[1:] # parse cmd arguments args = Arguments(args) logging.basicConfig(format='%(message)s ', level=args.verbose_level) logging.debug(f'ran with arguments {args}') repo = cwd flist_fname = os.path.join(repo, 'filelist') # run safety checks if not safety_checks(repo, home, args.action == Actions.INIT): logging.error(f'safety checks failed for {os.getcwd()}, exiting') return 1 # check for init if args.action == Actions.INIT: init_repo(repo, flist_fname) return 0 # parse filelist filelist = Filelist(flist_fname) # generate manifest for later cleaning manifest = filelist.manifest() # activate categories on filelist try: filelist = filelist.activate(args.categories) except RuntimeError: return 1 # set up git interface git = Git(repo) # set the dotfiles repo dotfiles = os.path.join(repo, 'dotfiles') logging.debug(f'dotfiles path is {dotfiles}') # init plugins plugins_data_dir = os.path.join(repo, '.plugins') plugins = { 'plain': PlainPlugin( data_dir=os.path.join(plugins_data_dir, 'plain'), repo_dir=os.path.join(dotfiles, 'plain'), hard=args.hard_mode), 'encrypt': EncryptPlugin( data_dir=os.path.join(plugins_data_dir, 'encrypt'), repo_dir=os.path.join(dotfiles, 'encrypt')) } plugin_dirs = {plugin: os.path.join(dotfiles, plugin) for plugin in plugins} if args.action in [Actions.UPDATE, Actions.RESTORE, Actions.CLEAN]: clean_ops = [] # calculate and apply file operations for plugin in plugins: # filter out filelist paths that use current plugin flist = {path: filelist[path]['categories'] for path in filelist if filelist[path]['plugin'] == plugin} if not flist: continue logging.debug(f'active filelist for plugin {plugin}: {flist}') plugin_dir = plugin_dirs[plugin] calc_ops = CalcOps(plugin_dir, home, plugins[plugin]) if args.action == Actions.UPDATE: calc_ops.update(flist).apply(args.dry_run) calc_ops.restore(flist).apply(args.dry_run) elif args.action == Actions.RESTORE: calc_ops.restore(flist).apply(args.dry_run) elif args.action == Actions.CLEAN: calc_ops.clean(flist).apply(args.dry_run) clean_ops.append(calc_ops.clean_repo(manifest[plugin])) plugins[plugin].clean_data(manifest[plugin]) # execute cleaning ops after everything else for clean_op in clean_ops: clean_op.apply(args.dry_run) elif args.action in [Actions.DIFF, Actions.COMMIT]: # calculate and apply git operations if args.action == Actions.DIFF: print('\n'.join(git.diff(ignore=['.plugins/']))) for plugin in plugins: calc_ops = CalcOps(plugin_dirs[plugin], home, plugins[plugin]) diff = calc_ops.diff(args.categories) if diff: print(f'\n{plugin}-plugin updates not yet in repo:') print('\n'.join(diff)) elif args.action == Actions.COMMIT: if not git.has_changes(): logging.warning('no changes detected in repo, not creating ' 'commit') return 0 git.add() msg = git.gen_commit_message(ignore=['.plugins/']) git.commit(msg) if git.has_remote(): ans = input('remote for repo detected, push to remote? [Yn] ') ans = ans if ans else 'y' if ans.lower() == 'y': git.push() logging.info('successfully pushed to git remote') elif args.action == Actions.PASSWD: logging.debug('attempting to change encryption password') repo = os.path.join(dotfiles, 'encrypt') if os.path.exists(repo): plugins['encrypt'].init_password() plugins['encrypt'].change_password(repo=repo) else: plugins['encrypt'].change_password() return 0