Пример #1
0
    def test_have_all(self, tmp_path):
        home = tmp_path / 'home'
        repo = tmp_path / 'repo'

        self.setup_repo(repo)

        assert safety_checks(repo, home, False)
Пример #2
0
    def test_nofilelist(self, tmp_path):
        home = tmp_path / 'home'
        repo = tmp_path / 'repo'

        self.setup_repo(repo)
        os.remove(repo / 'filelist')

        assert not safety_checks(repo, home, False)
Пример #3
0
    def test_nogit(self, tmp_path):
        home = tmp_path / 'home'
        repo = tmp_path / 'repo'

        self.setup_repo(repo)
        os.rmdir(repo / '.git')

        assert not safety_checks(repo, home, False)
Пример #4
0
    def test_old_dotgit(self, tmp_path, caplog):
        home = tmp_path / 'home'
        repo = tmp_path / 'repo'

        self.setup_repo(repo)
        open(repo / 'cryptlist', 'w').close()

        assert not safety_checks(repo, home, False)
        assert 'old dotgit repo' in caplog.text
Пример #5
0
    def test_other_empty(self, tmp_path):
        home = tmp_path / 'home'
        repo = tmp_path / 'repo'

        assert not safety_checks(repo, home, False)
Пример #6
0
    def test_init_empty(self, tmp_path):
        home = tmp_path / 'home'
        repo = tmp_path / 'repo'

        assert safety_checks(repo, home, True)
Пример #7
0
    def test_home(self, tmp_path):
        home = tmp_path / 'home'
        repo = tmp_path / 'repo'

        assert not safety_checks(home, home, True)
Пример #8
0
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