| 15 | |
| 16 | |
| 17 | def metasync(storage_a, storage_b, status, keys, conflict_resolution=None): |
| 18 | def _a_to_b(): |
| 19 | logger.info('Copying {} to {}'.format(key, storage_b)) |
| 20 | storage_b.set_meta(key, a) |
| 21 | status[key] = a |
| 22 | |
| 23 | def _b_to_a(): |
| 24 | logger.info('Copying {} to {}'.format(key, storage_a)) |
| 25 | storage_a.set_meta(key, b) |
| 26 | status[key] = b |
| 27 | |
| 28 | def _resolve_conflict(): |
| 29 | if a == b: |
| 30 | status[key] = a |
| 31 | elif conflict_resolution == 'a wins': |
| 32 | _a_to_b() |
| 33 | elif conflict_resolution == 'b wins': |
| 34 | _b_to_a() |
| 35 | else: |
| 36 | if callable(conflict_resolution): |
| 37 | logger.warning('Custom commands don\'t work on metasync.') |
| 38 | elif conflict_resolution is not None: |
| 39 | raise exceptions.UserError( |
| 40 | 'Invalid conflict resolution setting.' |
| 41 | ) |
| 42 | raise MetaSyncConflict(key) |
| 43 | |
| 44 | for key in keys: |
| 45 | a = storage_a.get_meta(key) |
| 46 | b = storage_b.get_meta(key) |
| 47 | s = normalize_meta_value(status.get(key)) |
| 48 | logger.debug('Key: {}'.format(key)) |
| 49 | logger.debug('A: {}'.format(a)) |
| 50 | logger.debug('B: {}'.format(b)) |
| 51 | logger.debug('S: {}'.format(s)) |
| 52 | |
| 53 | if a != s and b != s: |
| 54 | _resolve_conflict() |
| 55 | elif a != s and b == s: |
| 56 | _a_to_b() |
| 57 | elif a == s and b != s: |
| 58 | _b_to_a() |
| 59 | else: |
| 60 | assert a == b |
| 61 | |
| 62 | for key in set(status) - set(keys): |
| 63 | del status[key] |