Beispiel #1
0
def handle_conflict(key, action_1, client_1, action_2, client_2):
    print(
        "\n"
        'Conflict for "{}". Which version would you like to keep?\n'
        "   (1) {}{} updated at {} ({})\n"
        "   (2) {}{} updated at {} ({})\n"
        "   (d) View difference (requires the diff command)\n"
        "   (X) Skip this file\n".format(
            key,
            client_1.get_uri(),
            key,
            action_1.get_remote_datetime(),
            action_1.state,
            client_2.get_uri(),
            key,
            action_2.get_remote_datetime(),
            action_2.state,
        ),
        file=sys.stderr,
    )
    while True:
        choice = utils.get_input("Choice (default=skip): ")
        print("", file=sys.stderr)

        if choice == "d":
            show_diff(client_1, client_2, key)
        else:
            break

    if choice == "1":
        return Resolution.get_resolution(key, action_1, client_2, client_1)
    elif choice == "2":
        return Resolution.get_resolution(key, action_2, client_1, client_2)
Beispiel #2
0
 def test_repr(self):
     s3_client = s3.S3SyncClient(None, 'mortybucket', 'dimensional/portals')
     local_client = local.LocalSyncClient('/home/picklerick')
     resolution = Resolution(Resolution.CREATE, s3_client, local_client,
                             'foo', 20023)
     expected_repr = ("Resolution<action=CREATE, "
                      "to=s3://mortybucket/dimensional/portals/, "
                      "from=/home/picklerick/, "
                      "key=foo, timestamp=20023>")
     assert repr(resolution) == expected_repr
Beispiel #3
0
Datei: sync.py Projekt: epayet/S4
    def sync(self, conflict_choice=None, keys=None, dry_run=False):
        self.client_1.lock()
        self.client_2.lock()
        try:
            resolutions, unhandled_events = self.get_sync_states(keys)

            self.logger.debug(
                'There are %s unhandled events for the user to solve', len(unhandled_events)
            )
            self.logger.debug(
                'There are %s automatically resolved calls', len(resolutions)
            )
            for key in sorted(unhandled_events.keys()):
                action_1, action_2 = unhandled_events[key]
                if conflict_choice == '1':
                    resolutions[key] = Resolution.get_resolution(
                        key, action_1, self.client_2, self.client_1
                    )
                elif conflict_choice == '2':
                    resolutions[key] = Resolution.get_resolution(
                        key, action_2, self.client_1, self.client_2
                    )
                if self.conflict_handler is not None:
                    resolution = self.conflict_handler(
                        key, action_1, self.client_1, action_2, self.client_2
                    )
                    if resolution is not None:
                        resolutions[key] = resolution
                    else:
                        self.logger.info('Ignoring sync conflict for %s', key)
                else:
                    self.logger.info('Unable to resolve conflict for %s', key)

            self.run_resolutions(resolutions, dry_run)

        except KeyboardInterrupt:
            self.logger.warning('Session interrupted by Keyboard Interrupt. Aborting....')
        finally:
            self.client_1.unlock()
            self.client_2.unlock()
Beispiel #4
0
 def test_get_resolution_updated(self, state, action, s3_client,
                                 local_client):
     sync_state = SyncState(state, 1234, 4567)
     resolution = Resolution.get_resolution('foo/bar', sync_state,
                                            s3_client, local_client)
     assert resolution.action == action
     assert resolution.to_client == s3_client
     assert resolution.key == 'foo/bar'
     if state != SyncState.DELETED:
         assert resolution.timestamp == 1234
         assert resolution.from_client == local_client
     else:
         assert resolution.timestamp == 4567
         assert resolution.from_client is None
Beispiel #5
0
    def sync(self, conflict_choice=None, keys=None, dry_run=False):
        self.client_1.lock()
        self.client_2.lock()
        try:
            resolutions, unhandled_events = self.get_sync_states(keys)

            self.logger.debug(
                "There are %s unhandled events for the user to solve",
                len(unhandled_events),
            )
            self.logger.debug("There are %s automatically resolved calls",
                              len(resolutions))
            for key in sorted(unhandled_events.keys()):
                action_1, action_2 = unhandled_events[key]
                if conflict_choice == "1":
                    resolutions[key] = Resolution.get_resolution(
                        key, action_1, self.client_2, self.client_1)
                elif conflict_choice == "2":
                    resolutions[key] = Resolution.get_resolution(
                        key, action_2, self.client_1, self.client_2)
                if self.conflict_handler is not None:
                    resolution = self.conflict_handler(key, action_1,
                                                       self.client_1, action_2,
                                                       self.client_2)
                    if resolution is not None:
                        resolutions[key] = resolution
                    else:
                        self.logger.info("Ignoring sync conflict for %s", key)
                else:
                    self.logger.info("Unable to resolve conflict for %s", key)

            self.run_resolutions(resolutions, dry_run)

        finally:
            self.client_1.unlock()
            self.client_2.unlock()
Beispiel #6
0
    def get_sync_states(self, keys=None):
        # we store a list of resolutions to make sure we can handle everything before
        # running any updates on the file system and indexes
        resolutions = {}

        # list of unhandled events which cannot be solved automatically (or alternatively the
        # the automated solution has not yet been implemented)
        unhandled_events = {}

        self.logger.debug("Generating deferred calls based on client states")
        for key, state_1, state_2 in self.get_states(keys):
            self.logger.debug("%s: %s %s", key, state_1, state_2)
            if (state_1.state == SyncState.NOCHANGES
                    and state_2.state == SyncState.NOCHANGES):
                if state_1.remote_timestamp == state_2.remote_timestamp:
                    continue
                elif state_1.remote_timestamp > state_2.remote_timestamp:
                    resolutions[key] = Resolution(
                        Resolution.UPDATE,
                        self.client_2,
                        self.client_1,
                        key,
                        state_1.remote_timestamp,
                    )
                elif state_2.remote_timestamp > state_1.remote_timestamp:
                    resolutions[key] = Resolution(
                        Resolution.UPDATE,
                        self.client_1,
                        self.client_2,
                        key,
                        state_2.remote_timestamp,
                    )

            elif (state_1.state == SyncState.CREATED
                  and state_2.state == SyncState.DOESNOTEXIST):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_2,
                    self.client_1,
                    key,
                    state_1.local_timestamp,
                )

            elif (state_2.state == SyncState.CREATED
                  and state_1.state == SyncState.DOESNOTEXIST):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_1,
                    self.client_2,
                    key,
                    state_2.local_timestamp,
                )

            elif (state_1.state == SyncState.NOCHANGES
                  and state_2.state == SyncState.DOESNOTEXIST):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_2,
                    self.client_1,
                    key,
                    state_1.remote_timestamp,
                )

            elif (state_2.state == SyncState.NOCHANGES
                  and state_1.state == SyncState.DOESNOTEXIST):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_1,
                    self.client_2,
                    key,
                    state_2.remote_timestamp,
                )
            elif (state_1.state == SyncState.UPDATED
                  and state_2.state == SyncState.DOESNOTEXIST):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_2,
                    self.client_1,
                    key,
                    state_1.local_timestamp,
                )

            elif (state_2.state == SyncState.UPDATED
                  and state_1.state == SyncState.DOESNOTEXIST):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_2,
                    self.client_1,
                    key,
                    state_1.local_timestamp,
                )

            elif state_1.state in (
                    SyncState.DELETED,
                    SyncState.DOESNOTEXIST,
            ) and state_2.state in (SyncState.DELETED, SyncState.DOESNOTEXIST):
                # nothing to do, they have already both been deleted/do not exist
                continue

            elif (state_1.state == SyncState.UPDATED
                  and state_2.state == SyncState.NOCHANGES
                  and state_1.remote_timestamp == state_2.remote_timestamp):
                resolutions[key] = Resolution(
                    Resolution.UPDATE,
                    self.client_2,
                    self.client_1,
                    key,
                    state_1.local_timestamp,
                )

            elif (state_2.state == SyncState.UPDATED
                  and state_1.state == SyncState.NOCHANGES
                  and state_1.remote_timestamp == state_2.remote_timestamp):
                resolutions[key] = Resolution(
                    Resolution.UPDATE,
                    self.client_1,
                    self.client_2,
                    key,
                    state_2.local_timestamp,
                )

            elif (state_1.state == SyncState.DELETED
                  and state_2.state == SyncState.NOCHANGES
                  and state_1.remote_timestamp == state_2.remote_timestamp):
                resolutions[key] = Resolution(
                    Resolution.DELETE,
                    self.client_2,
                    None,
                    key,
                    state_1.remote_timestamp,
                )

            elif (state_2.state == SyncState.DELETED
                  and state_1.state == SyncState.NOCHANGES
                  and state_1.remote_timestamp == state_2.remote_timestamp):
                resolutions[key] = Resolution(
                    Resolution.DELETE,
                    self.client_1,
                    None,
                    key,
                    state_2.remote_timestamp,
                )

            elif (state_1.state == SyncState.DELETED
                  and state_2.state == SyncState.CREATED
                  and state_1.remote_timestamp == state_2.remote_timestamp):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_1,
                    self.client_2,
                    key,
                    state_2.local_timestamp,
                )

            elif (state_2.state == SyncState.DELETED
                  and state_1.state == SyncState.CREATED
                  and state_1.remote_timestamp == state_2.remote_timestamp):
                resolutions[key] = Resolution(
                    Resolution.CREATE,
                    self.client_2,
                    self.client_1,
                    key,
                    state_1.local_timestamp,
                )

            else:
                unhandled_events[key] = (state_1, state_2)

            self.logger.debug("Action=%s", resolutions.get(key))

        return resolutions, unhandled_events
Beispiel #7
0
 def test_equal_wrong_instance(self):
     resolution = Resolution(Resolution.CREATE, None, None, 'bar', 23232)
     assert resolution != "Not a Resolution"
Beispiel #8
0
 def test_invalid_sync_state(self):
     with pytest.raises(ValueError) as exc:
         Resolution.get_resolution('', SyncState('Invalid', None, None),
                                   None, None)
     assert exc.value
Beispiel #9
0
 def test_not_equal(self):
     resolution_1 = Resolution(Resolution.UPDATE, None, None, 'fffff',
                               232323)
     resolution_2 = Resolution(Resolution.DELETE, None, None, 'wew', 3823)
     assert resolution_1 != resolution_2
Beispiel #10
0
 def test_equal(self):
     resolution_1 = Resolution(Resolution.UPDATE, None, None, 'fffff',
                               232323)
     resolution_2 = Resolution(Resolution.UPDATE, None, None, 'fffff',
                               232323)
     assert resolution_1 == resolution_2
Beispiel #11
0
 def test_equal_to_self(self):
     resolution = Resolution(Resolution.UPDATE, None, None, 'fffff', 232323)
     assert resolution == resolution
Beispiel #12
0
 def test_not_equal(self):
     resolution_1 = Resolution(Resolution.UPDATE, None, None, "fffff",
                               232323)
     resolution_2 = Resolution(Resolution.DELETE, None, None, "wew", 3823)
     assert resolution_1 != resolution_2