From 2e2349c46d46ed11418caec1a490c1883332e149 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Tue, 16 Dec 2014 17:20:02 +0100 Subject: [PATCH] Add discover command --- tests/test_cli.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++ vdirsyncer/cli.py | 46 +++++++++++++++++++++++++++++++++------ 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 68e4eb2..b65f8ac 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -349,3 +349,58 @@ def test_invalid_pairs_as_cli_arg(tmpdir): env={'VDIRSYNCER_CONFIG': str(cfg)}) assert result.exception assert 'pair foobar: collection d not found' in result.output.lower() + + +def test_discover_command(tmpdir): + cfg = tmpdir.join('config') + cfg.write(dedent(''' + [general] + status_path = {0}/status/ + + [storage foo] + type = filesystem + path = {0}/foo/ + fileext = .txt + + [storage bar] + type = filesystem + path = {0}/bar/ + fileext = .txt + + [pair foobar] + a = foo + b = bar + collections = from a + ''').format(str(tmpdir))) + + foo = tmpdir.mkdir('foo') + tmpdir.mkdir('bar') + + foo.mkdir('a') + foo.mkdir('b') + foo.mkdir('c') + + runner = CliRunner() + result = runner.invoke(cli.app, ['sync'], + env={'VDIRSYNCER_CONFIG': str(cfg)}) + assert not result.exception + lines = result.output.splitlines() + assert lines[0].startswith('Discovering') + assert 'Syncing foobar/a' in lines + assert 'Syncing foobar/b' in lines + assert 'Syncing foobar/c' in lines + + foo.mkdir('d') + result = runner.invoke(cli.app, ['sync'], + env={'VDIRSYNCER_CONFIG': str(cfg)}) + assert not result.exception + assert 'Syncing foobar/d' not in result.output + + result = runner.invoke(cli.app, ['discover'], + env={'VDIRSYNCER_CONFIG': str(cfg)}) + assert not result.exception + + result = runner.invoke(cli.app, ['sync'], + env={'VDIRSYNCER_CONFIG': str(cfg)}) + assert not result.exception + assert 'Syncing foobar/d' in result.output diff --git a/vdirsyncer/cli.py b/vdirsyncer/cli.py index 029ed47..d4ea850 100644 --- a/vdirsyncer/cli.py +++ b/vdirsyncer/cli.py @@ -432,21 +432,23 @@ def _create_app(): raise CliError('Error during reading config {}: {}' .format(fname, e)) + max_workers_option = click.option( + '--max-workers', default=0, type=click.IntRange(min=0, max=None), + help=('Use at most this many connections, 0 means unlimited.') + ) + @app.command() @click.argument('pairs', nargs=-1) @click.option('--force-delete/--no-force-delete', help=('Disable data-loss protection for the given pairs. ' 'Can be passed multiple times')) - @click.option('--max-workers', - default=0, type=click.IntRange(min=0, max=None), - help=('Use at most this many connections, 0 means ' - 'unlimited.')) + @max_workers_option @click.pass_context @catch_errors def sync(ctx, pairs, force_delete, max_workers): ''' - Synchronize the given pairs. If no pairs are given, all will be - synchronized. + Synchronize the given collections or pairs. If no arguments are given, + all will be synchronized. Examples: `vdirsyncer sync` will sync everything configured. @@ -471,6 +473,38 @@ def _create_app(): wq.join() + @app.command() + @click.argument('pairs', nargs=-1) + @max_workers_option + @click.pass_context + @catch_errors + def discover(ctx, pairs, max_workers): + ''' + Refresh collection cache for the given pairs. + ''' + general, all_pairs, all_storages = ctx.obj['config'] + cli_logger.debug('Using {} maximal workers.'.format(max_workers)) + wq = WorkerQueue(max_workers) + + for pair in (pairs or all_pairs): + try: + name_a, name_b, pair_options, storage_defaults = \ + all_pairs[pair] + except KeyError: + raise CliError('Pair not found: {}\n' + 'These are the pairs found: {}' + .format(pair, list(all_pairs))) + + wq.spawn_worker() + wq.put(functools.partial( + (lambda wq, **kwargs: collections_for_pair(**kwargs)), + status_path=general['status_path'], name_a=name_a, + name_b=name_b, pair_name=pair, config_a=all_storages[name_a], + config_b=all_storages[name_b], pair_options=pair_options, + skip_cache=True)) + + wq.join() + return app app = main = _create_app()