mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-03-30 09:45:53 +00:00
parent
63e9e55bbe
commit
c6e185d8a3
2 changed files with 96 additions and 26 deletions
|
|
@ -510,3 +510,63 @@ def test_partial_sync(tmpdir, runner, partial_sync):
|
|||
assert not r.exception
|
||||
assert baritem.exists()
|
||||
assert fooitem.exists()
|
||||
|
||||
|
||||
def test_fetch_only_necessary_params(tmpdir, runner):
|
||||
fetched_file = tmpdir.join('fetched_flag')
|
||||
fetch_script = tmpdir.join('fetch_script')
|
||||
fetch_script.write(dedent('''
|
||||
set -e
|
||||
touch "{}"
|
||||
echo ".txt"
|
||||
'''.format(str(fetched_file))))
|
||||
|
||||
runner.write_with_general(dedent('''
|
||||
[pair foobar]
|
||||
a = foo
|
||||
b = bar
|
||||
collections = null
|
||||
|
||||
[pair bambar]
|
||||
a = bam
|
||||
b = bar
|
||||
collections = null
|
||||
|
||||
[storage foo]
|
||||
type = filesystem
|
||||
path = {path}
|
||||
fileext = .txt
|
||||
|
||||
[storage bar]
|
||||
type = filesystem
|
||||
path = {path}
|
||||
fileext = .txt
|
||||
|
||||
[storage bam]
|
||||
type = filesystem
|
||||
path = {path}
|
||||
fileext.fetch = ["command", "sh", "{script}"]
|
||||
'''.format(path=str(tmpdir.mkdir('bogus')), script=str(fetch_script))))
|
||||
|
||||
def fetched():
|
||||
try:
|
||||
fetched_file.remove()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
r = runner.invoke(['discover'])
|
||||
assert not r.exception
|
||||
assert fetched()
|
||||
|
||||
r = runner.invoke(['sync', 'foobar'])
|
||||
assert not r.exception
|
||||
assert not fetched()
|
||||
|
||||
r = runner.invoke(['sync'])
|
||||
assert not r.exception
|
||||
assert fetched()
|
||||
|
||||
r = runner.invoke(['sync', 'bambar'])
|
||||
assert not r.exception
|
||||
assert fetched()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from . import cli_logger
|
|||
from .fetchparams import expand_fetch_params
|
||||
from .utils import storage_class_from_config
|
||||
from .. import PROJECT_HOME, exceptions
|
||||
from ..utils import expand_path
|
||||
from ..utils import cached_property, expand_path
|
||||
|
||||
try:
|
||||
from ConfigParser import RawConfigParser
|
||||
|
|
@ -253,21 +253,30 @@ class PairConfig(object):
|
|||
self.name_a = options.pop('a')
|
||||
self.name_b = options.pop('b')
|
||||
|
||||
self.config_a = self._config.get_storage_args(self.name_a)
|
||||
self.config_b = self._config.get_storage_args(self.name_b)
|
||||
|
||||
self._set_conflict_resolution(options)
|
||||
self._set_partial_sync(options)
|
||||
self._set_collections(options)
|
||||
self._partial_sync = options.pop('partial_sync', None)
|
||||
self.metadata = options.pop('metadata', None) or ()
|
||||
|
||||
self.conflict_resolution = \
|
||||
self._process_conflict_resolution_param(
|
||||
options.pop('conflict_resolution', None))
|
||||
|
||||
try:
|
||||
self.collections = options.pop('collections')
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'collections parameter missing.\n\n'
|
||||
'As of 0.9.0 this parameter has no default anymore. '
|
||||
'Set `collections = null` explicitly in your pair config.'
|
||||
)
|
||||
else:
|
||||
_validate_collections_param(self.collections)
|
||||
|
||||
if options:
|
||||
raise ValueError('Unknown options: {}'.format(', '.join(options)))
|
||||
|
||||
def _set_conflict_resolution(self, options):
|
||||
conflict_resolution = options.pop('conflict_resolution', None)
|
||||
def _process_conflict_resolution_param(self, conflict_resolution):
|
||||
if conflict_resolution in (None, 'a wins', 'b wins'):
|
||||
self.conflict_resolution = conflict_resolution
|
||||
return conflict_resolution
|
||||
elif isinstance(conflict_resolution, list) and \
|
||||
len(conflict_resolution) > 1 and \
|
||||
conflict_resolution[0] == 'command':
|
||||
|
|
@ -282,12 +291,25 @@ class PairConfig(object):
|
|||
ui_worker = get_ui_worker()
|
||||
return ui_worker.put(inner)
|
||||
|
||||
self.conflict_resolution = resolve
|
||||
return resolve
|
||||
else:
|
||||
raise ValueError('Invalid value for `conflict_resolution`.')
|
||||
|
||||
def _set_partial_sync(self, options):
|
||||
partial_sync = options.pop('partial_sync', None)
|
||||
# The following parameters are lazily evaluated because evaluating
|
||||
# self.config_a would expand all `x.fetch` parameters. This is costly and
|
||||
# unnecessary if the pair is not actually synced.
|
||||
|
||||
@cached_property
|
||||
def config_a(self):
|
||||
return self._config.get_storage_args(self.name_a)
|
||||
|
||||
@cached_property
|
||||
def config_b(self):
|
||||
return self._config.get_storage_args(self.name_b)
|
||||
|
||||
@cached_property
|
||||
def partial_sync(self):
|
||||
partial_sync = self._partial_sync
|
||||
if partial_sync is not None:
|
||||
cls_a, _ = storage_class_from_config(self.config_a)
|
||||
cls_b, _ = storage_class_from_config(self.config_b)
|
||||
|
|
@ -305,19 +327,7 @@ class PairConfig(object):
|
|||
if partial_sync not in ('ignore', 'revert', 'error'):
|
||||
raise ValueError('Invalid value for `partial_sync`.')
|
||||
|
||||
self.partial_sync = partial_sync
|
||||
|
||||
def _set_collections(self, options):
|
||||
try:
|
||||
self.collections = options.pop('collections')
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'collections parameter missing.\n\n'
|
||||
'As of 0.9.0 this parameter has no default anymore. '
|
||||
'Set `collections = null` explicitly in your pair config.'
|
||||
)
|
||||
else:
|
||||
_validate_collections_param(self.collections)
|
||||
return partial_sync
|
||||
|
||||
|
||||
class CollectionConfig(object):
|
||||
|
|
|
|||
Loading…
Reference in a new issue