mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-03-25 08:55:50 +00:00
Add CLI for partial_sync
This commit is contained in:
parent
8ca5446e02
commit
827299ef24
4 changed files with 76 additions and 2 deletions
|
|
@ -101,6 +101,13 @@ Pair Section
|
|||
|
||||
Vdirsyncer never attempts to "automatically merge" the two items.
|
||||
|
||||
- ``partial_sync``: Assume A is read-only, B not. If you change items on B,
|
||||
vdirsyncer can't sync the changes to A. What should happen instead?
|
||||
|
||||
- ``error``: An error is shown.
|
||||
- ``ignore``: The change is ignored.
|
||||
- ``revert`` (default): The change is reverted on next sync.
|
||||
|
||||
- ``metadata``: Metadata keys that should be synchronized when ``vdirsyncer
|
||||
metasync`` is executed. Example::
|
||||
|
||||
|
|
|
|||
|
|
@ -449,3 +449,64 @@ def test_conflict_resolution(tmpdir, runner, resolution, expect_foo,
|
|||
|
||||
assert fooitem.read() == expect_foo
|
||||
assert baritem.read() == expect_bar
|
||||
|
||||
|
||||
@pytest.mark.parametrize('partial_sync', ['error', 'ignore', 'revert', None])
|
||||
def test_partial_sync(tmpdir, runner, partial_sync):
|
||||
runner.write_with_general(dedent('''
|
||||
[pair foobar]
|
||||
a = foo
|
||||
b = bar
|
||||
collections = null
|
||||
{partial_sync}
|
||||
|
||||
[storage foo]
|
||||
type = filesystem
|
||||
fileext = .txt
|
||||
path = {base}/foo
|
||||
|
||||
[storage bar]
|
||||
type = filesystem
|
||||
read_only = true
|
||||
fileext = .txt
|
||||
path = {base}/bar
|
||||
'''.format(
|
||||
partial_sync=('partial_sync = {}\n'.format(partial_sync)
|
||||
if partial_sync else ''),
|
||||
base=str(tmpdir)
|
||||
)))
|
||||
|
||||
foo = tmpdir.mkdir('foo')
|
||||
bar = tmpdir.mkdir('bar')
|
||||
|
||||
foo.join('other.txt').write('UID:other')
|
||||
bar.join('other.txt').write('UID:other')
|
||||
|
||||
baritem = bar.join('lol.txt')
|
||||
baritem.write('UID:lol')
|
||||
|
||||
r = runner.invoke(['discover'])
|
||||
assert not r.exception
|
||||
|
||||
r = runner.invoke(['sync'])
|
||||
assert not r.exception
|
||||
|
||||
fooitem = foo.join('lol.txt')
|
||||
fooitem.remove()
|
||||
|
||||
r = runner.invoke(['sync'])
|
||||
|
||||
if partial_sync == 'error':
|
||||
assert r.exception
|
||||
assert 'Attempted change' in r.output
|
||||
elif partial_sync == 'ignore':
|
||||
assert baritem.exists()
|
||||
r = runner.invoke(['sync'])
|
||||
assert not r.exception
|
||||
assert baritem.exists()
|
||||
else:
|
||||
assert baritem.exists()
|
||||
r = runner.invoke(['sync'])
|
||||
assert not r.exception
|
||||
assert baritem.exists()
|
||||
assert fooitem.exists()
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ class PairConfig(object):
|
|||
self.options = options
|
||||
|
||||
self._set_conflict_resolution()
|
||||
self._set_partial_sync()
|
||||
self._set_collections()
|
||||
|
||||
def _set_conflict_resolution(self):
|
||||
|
|
@ -278,6 +279,11 @@ class PairConfig(object):
|
|||
else:
|
||||
raise ValueError('Invalid value for `conflict_resolution`.')
|
||||
|
||||
def _set_partial_sync(self):
|
||||
self.partial_sync = self.options.pop('partial_sync', 'revert')
|
||||
if self.partial_sync not in ('ignore', 'revert', 'error'):
|
||||
raise ValueError('Invalid value for `partial_sync`.')
|
||||
|
||||
def _set_collections(self):
|
||||
try:
|
||||
collections = self.options['collections']
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ def sync_collection(wq, collection, general, force_delete):
|
|||
a, b, status,
|
||||
conflict_resolution=pair.conflict_resolution,
|
||||
force_delete=force_delete,
|
||||
error_callback=error_callback
|
||||
|
||||
error_callback=error_callback,
|
||||
partial_sync=pair.partial_sync
|
||||
)
|
||||
|
||||
save_status(general['status_path'], pair.name, collection.name,
|
||||
|
|
|
|||
Loading…
Reference in a new issue