diff --git a/tests/test_cli.py b/tests/test_cli.py index 403a864b0..01cb48d12 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -278,18 +278,19 @@ def test_collections_cache_invalidation(tmpdir): [pair foobar] a = foo b = bar + collections = a, b, c ''').format(str(tmpdir))) foo = tmpdir.mkdir('foo') - tmpdir.mkdir('bar') - foo.join('itemone.txt').write('UID:itemone') + bar = tmpdir.mkdir('bar') + foo.mkdir('a').join('itemone.txt').write('UID:itemone') runner = CliRunner() result = runner.invoke(cli.app, ['sync'], env={'VDIRSYNCER_CONFIG': str(cfg)}) assert not result.exception - rv = tmpdir.join('bar').listdir() + rv = bar.join('a').listdir() assert len(rv) == 1 assert rv[0].basename == 'itemone.txt' @@ -310,14 +311,16 @@ def test_collections_cache_invalidation(tmpdir): [pair foobar] a = foo b = bar + collections = a, b, c ''').format(str(tmpdir))) tmpdir.join('status').remove() + bar2 = tmpdir.mkdir('bar2') result = runner.invoke(cli.app, ['sync'], env={'VDIRSYNCER_CONFIG': str(cfg)}) assert not result.exception - rv = tmpdir.join('bar').listdir() - rv2 = tmpdir.join('bar2').listdir() + rv = bar.join('a').listdir() + rv2 = tmpdir.join('bar2').join('a').listdir() assert len(rv) == len(rv2) == 1 assert rv[0].basename == rv2[0].basename == 'itemone.txt' diff --git a/vdirsyncer/cli.py b/vdirsyncer/cli.py index f12a44096..9421e982d 100644 --- a/vdirsyncer/cli.py +++ b/vdirsyncer/cli.py @@ -191,20 +191,28 @@ def _discover_from_config(config): rv[args['collection']] = args return rv - def _get_coll(discovered, collection, storage_name): + def _get_coll(discovered, collection, storage_name, config): try: return discovered[collection] except KeyError: - raise CliError( - 'Unable to find collection {collection!r} for storage ' - '{storage_name!r}.\n For pair {pair_name!r}, you wanted to ' - 'use the collections {shortcut!r}, which yielded ' - '{collection!r} (amongst others). Vdirsyncer was unable to ' - 'find an equivalent collection for the other storage.'.format( - collection=collection, shortcut=shortcut, - storage_name=storage_name, pair_name=pair_name + storage_type = config['type'] + cls, config = storage_class_from_config(config) + try: + rv = cls.join_collection(collection=collection, **config) + rv['type'] = storage_type + return rv + except NotImplementedError: + raise CliError( + 'Unable to find collection {collection!r} for storage ' + '{storage_name!r}.\n For pair {pair_name!r}, you wanted ' + 'to use the collections {shortcut!r}, which yielded ' + '{collection!r} (amongst others). Vdirsyncer was unable ' + 'to find an equivalent collection for the other ' + 'storage.'.format( + collection=collection, shortcut=shortcut, + storage_name=storage_name, pair_name=pair_name + ) ) - ) shortcuts = set(_parse_old_config_list_value(pair_options, 'collections')) if not shortcuts: @@ -221,8 +229,8 @@ def _get_coll(discovered, collection, storage_name): collections = [shortcut] for collection in collections: - a_args = _get_coll(a_discovered, collection, name_a) - b_args = _get_coll(b_discovered, collection, name_b) + a_args = _get_coll(a_discovered, collection, name_a, config_a) + b_args = _get_coll(b_discovered, collection, name_b, config_b) yield collection, a_args, b_args diff --git a/vdirsyncer/storage/base.py b/vdirsyncer/storage/base.py index bff563157..48b0beb02 100644 --- a/vdirsyncer/storage/base.py +++ b/vdirsyncer/storage/base.py @@ -89,6 +89,13 @@ class to obtain a storage instance pointing to this collection. It ''' raise NotImplementedError() + @classmethod + def join_collection(cls, collection, **kwargs): + '''Append the collection to the URL or path specified in ``**kwargs`` + and return the new arguments. + ''' + raise NotImplementedError() + def __repr__(self): return self.instance_name or '<{}(**{})>'.format( self.__class__.__name__, diff --git a/vdirsyncer/storage/filesystem.py b/vdirsyncer/storage/filesystem.py index bfae4bdce..9dc28e5f2 100644 --- a/vdirsyncer/storage/filesystem.py +++ b/vdirsyncer/storage/filesystem.py @@ -57,6 +57,11 @@ def discover(cls, path, **kwargs): **kwargs) yield args + @classmethod + def join_collection(cls, collection, **kwargs): + kwargs['path'] = os.path.join(kwargs['path'], collection) + return kwargs + def _get_filepath(self, href): return os.path.join(self.path, href)