Example #1
0
    def do_readlocked_repository_request(self, repository, revision_id):
        """Return the result of repository.get_revision_graph(revision_id).

        Deprecated as of bzr 1.4, but supported for older clients.
        
        :param repository: The repository to query in.
        :param revision_id: The utf8 encoded revision_id to get a graph from.
        :return: A smart server response where the body contains an utf8
            encoded flattened list of the revision graph.
        """
        if not revision_id:
            revision_id = None

        lines = []
        graph = repository.get_graph()
        if revision_id:
            search_ids = [revision_id]
        else:
            search_ids = repository.all_revision_ids()
        search = graph._make_breadth_first_searcher(search_ids)
        transitive_ids = set()
        map(transitive_ids.update, list(search))
        parent_map = graph.get_parent_map(transitive_ids)
        revision_graph = _strip_NULL_ghosts(parent_map)
        if revision_id and revision_id not in revision_graph:
            # Note that we return an empty body, rather than omitting the body.
            # This way the client knows that it can always expect to find a body
            # in the response for this method, even in the error case.
            return FailedSmartServerResponse(('nosuchrevision', revision_id),
                                             '')

        for revision, parents in revision_graph.items():
            lines.append(' '.join((revision, ) + tuple(parents)))

        return SuccessfulSmartServerResponse(('ok', ), '\n'.join(lines))
Example #2
0
    def do_tip_change_with_locked_branch(self, branch, new_last_revision_id,
                                         allow_divergence,
                                         allow_overwrite_descendant):
        """Set the last revision of the branch.

        New in 1.6.
        
        :param new_last_revision_id: the revision ID to set as the last
            revision of the branch.
        :param allow_divergence: A flag.  If non-zero, change the revision ID
            even if the new_last_revision_id's ancestry has diverged from the
            current last revision.  If zero, a 'Diverged' error will be
            returned if new_last_revision_id is not a descendant of the current
            last revision.
        :param allow_overwrite_descendant:  A flag.  If zero and
            new_last_revision_id is not a descendant of the current last
            revision, then the last revision will not be changed.  If non-zero
            and there is no divergence, then the last revision is always
            changed.

        :returns: on success, a tuple of ('ok', revno, revision_id), where
            revno and revision_id are the new values of the current last
            revision info.  The revision_id might be different to the
            new_last_revision_id if allow_overwrite_descendant was not set.
        """
        do_not_overwrite_descendant = not allow_overwrite_descendant
        try:
            last_revno, last_rev = branch.last_revision_info()
            graph = branch.repository.get_graph()
            if not allow_divergence or do_not_overwrite_descendant:
                relation = branch._revision_relations(last_rev,
                                                      new_last_revision_id,
                                                      graph)
                if relation == 'diverged' and not allow_divergence:
                    return FailedSmartServerResponse(('Diverged', ))
                if relation == 'a_descends_from_b' and do_not_overwrite_descendant:
                    return SuccessfulSmartServerResponse(
                        ('ok', last_revno, last_rev))
            new_revno = graph.find_distance_to_null(new_last_revision_id,
                                                    [(last_rev, last_revno)])
            branch.set_last_revision_info(new_revno, new_last_revision_id)
        except errors.GhostRevisionsHaveNoRevno:
            return FailedSmartServerResponse(
                ('NoSuchRevision', new_last_revision_id))
        return SuccessfulSmartServerResponse(
            ('ok', new_revno, new_last_revision_id))
Example #3
0
 def do_tip_change_with_locked_branch(self, branch, new_revno,
                                      new_last_revision_id):
     try:
         branch.set_last_revision_info(int(new_revno), new_last_revision_id)
     except errors.NoSuchRevision:
         return FailedSmartServerResponse(
             ('NoSuchRevision', new_last_revision_id))
     return SuccessfulSmartServerResponse(('ok', ))
Example #4
0
 def do_with_locked_branch(self, branch, *args):
     try:
         return self.do_tip_change_with_locked_branch(branch, *args)
     except errors.TipChangeRejected, e:
         msg = e.msg
         if isinstance(msg, unicode):
             msg = msg.encode('utf-8')
         return FailedSmartServerResponse(('TipChangeRejected', msg))
Example #5
0
 def do_repository_request(self, repository, token=''):
     # XXX: this probably should not have a token.
     if token == '':
         token = None
     try:
         token = repository.lock_write(token=token).repository_token
     except errors.LockContention, e:
         return FailedSmartServerResponse(('LockContention',))
Example #6
0
 def test__str__(self):
     """SmartServerResponses can be stringified."""
     self.assertEqual(
         "<SmartServerResponse status=OK args=('args',) body='body'>",
         str(SuccessfulSmartServerResponse(('args',), 'body')))
     self.assertEqual(
         "<SmartServerResponse status=ERR args=('args',) body='body'>",
         str(FailedSmartServerResponse(('args',), 'body')))
Example #7
0
 def do_tip_change_with_locked_branch(self, branch, new_last_revision_id):
     if new_last_revision_id == 'null:':
         branch.set_revision_history([])
     else:
         if not branch.repository.has_revision(new_last_revision_id):
             return FailedSmartServerResponse(
                 ('NoSuchRevision', new_last_revision_id))
         branch.generate_revision_history(new_last_revision_id)
     return SuccessfulSmartServerResponse(('ok', ))
Example #8
0
 def do_bzrdir_request(self):
     """open a branch at path and return the branch reference or branch."""
     try:
         reference_url = self._bzrdir.get_branch_reference()
         if reference_url is None:
             return SuccessfulSmartServerResponse(('ok', ''))
         else:
             return SuccessfulSmartServerResponse(('ok', reference_url))
     except errors.NotBranchError, e:
         return FailedSmartServerResponse(('nobranch', ))
Example #9
0
    def do_bzrdir_request(self, name=None):
        """Destroy the branch with the specified name.

        New in 2.5.0.
        :return: On success, 'ok'.
        """
        try:
            self._bzrdir.destroy_branch(name)
        except errors.NotBranchError, e:
            return FailedSmartServerResponse(('nobranch', ))
Example #10
0
 def body_stream(self, stream, repository):
     byte_stream = _stream_to_byte_stream(stream, repository._format)
     try:
         for bytes in byte_stream:
             yield bytes
     except errors.RevisionNotPresent, e:
         # This shouldn't be able to happen, but as we don't buffer
         # everything it can in theory happen.
         repository.unlock()
         yield FailedSmartServerResponse(('NoSuchRevision', e.revision_id))
Example #11
0
 def test_not_allow_diverged(self):
     """If allow_diverged is not passed, then setting a divergent history
     returns a Diverged error.
     """
     self.make_branch_with_divergent_history()
     self.assertEqual(
         FailedSmartServerResponse(('Diverged',)),
         self.set_last_revision('child-1', 2))
     # The branch tip was not changed.
     self.assertEqual('child-2', self.tree.branch.last_revision())
Example #12
0
 def do_repository_request(self, repository, lock_token, write_group_tokens):
     """Abort a write group."""
     repository.lock_write(token=lock_token)
     try:
         try:
             repository.resume_write_group(write_group_tokens)
         except errors.UnresumableWriteGroup, e:
             return FailedSmartServerResponse(
                 ('UnresumableWriteGroup', e.write_groups, e.reason))
         else:
Example #13
0
class SmartServerRepositoryLockWrite(SmartServerRepositoryRequest):
    def do_repository_request(self, repository, token=''):
        # XXX: this probably should not have a token.
        if token == '':
            token = None
        try:
            token = repository.lock_write(token=token)
        except errors.LockContention, e:
            return FailedSmartServerResponse(('LockContention', ))
        except errors.UnlockableTransport:
            return FailedSmartServerResponse(('UnlockableTransport', ))
Example #14
0
    def do_bzrdir_request(self, name=None):
        """Destroy the repository.

        New in 2.5.0.

        :return: On success, 'ok'.
        """
        try:
            self._bzrdir.destroy_repository()
        except errors.NoRepositoryPresent, e:
            return FailedSmartServerResponse(('norepository', ))
Example #15
0
 def do_repository_request(self, repository, lock_token):
     """Start a write group."""
     repository.lock_write(token=lock_token)
     try:
         repository.start_write_group()
         try:
             tokens = repository.suspend_write_group()
         except errors.UnsuspendableWriteGroup:
             return FailedSmartServerResponse(('UnsuspendableWriteGroup',))
     finally:
         repository.unlock()
     return SuccessfulSmartServerResponse(('ok', tokens))
Example #16
0
 def do_with_branch(self, branch, branch_token='', repo_token=''):
     if branch_token == '':
         branch_token = None
     if repo_token == '':
         repo_token = None
     try:
         repo_token = branch.repository.lock_write(token=repo_token)
         try:
             branch_token = branch.lock_write(token=branch_token)
         finally:
             # this leaves the repository with 1 lock
             branch.repository.unlock()
     except errors.LockContention:
         return FailedSmartServerResponse(('LockContention', ))
     except errors.TokenMismatch:
         return FailedSmartServerResponse(('TokenMismatch', ))
     except errors.UnlockableTransport:
         return FailedSmartServerResponse(('UnlockableTransport', ))
     except errors.LockFailed, e:
         return FailedSmartServerResponse(
             ('LockFailed', str(e.lock), str(e.why)))
Example #17
0
    def do_repository_request(self, repository, revision_id):
        """Return the result of repository.get_signature_text().

        :param repository: The repository to query in.
        :return: A smart server response of with the signature text as
            body.
        """
        try:
            text = repository.get_signature_text(revision_id)
        except errors.NoSuchRevision, err:
            return FailedSmartServerResponse(
                ('nosuchrevision', err.revision))
Example #18
0
 def do_bzrdir_request(self):
     """open a branch at path and return the reference or format."""
     try:
         reference_url = self._bzrdir.get_branch_reference()
         if reference_url is None:
             br = self._bzrdir.open_branch(ignore_fallbacks=True)
             format = br._format.network_name()
             return SuccessfulSmartServerResponse(('branch', format))
         else:
             return SuccessfulSmartServerResponse(('ref', reference_url))
     except errors.NotBranchError, e:
         return FailedSmartServerResponse(('nobranch', ))
Example #19
0
 def test_TipChangeRejected(self):
     """If a pre_change_branch_tip hook raises TipChangeRejected, the verb
     returns TipChangeRejected.
     """
     rejection_message = u'rejection message\N{INTERROBANG}'
     def hook_that_rejects(params):
         raise errors.TipChangeRejected(rejection_message)
     Branch.hooks.install_named_hook(
         'pre_change_branch_tip', hook_that_rejects, None)
     self.assertEqual(
         FailedSmartServerResponse(
             ('TipChangeRejected', rejection_message.encode('utf-8'))),
         self.set_last_revision('null:', 0))
Example #20
0
    def do_with_branch(self, branch, revid):
        """Return branch.revision_id_to_revno().

        New in 2.5.

        The revno is encoded in decimal, the revision_id is encoded as utf8.
        """
        try:
            dotted_revno = branch.revision_id_to_dotted_revno(revid)
        except errors.NoSuchRevision:
            return FailedSmartServerResponse(('NoSuchRevision', revid))
        return SuccessfulSmartServerResponse(('ok', ) +
                                             tuple(map(str, dotted_revno)))
Example #21
0
 def do_with_branch(self, branch, branch_token, repo_token):
     try:
         branch.repository.lock_write(token=repo_token)
         try:
             branch.lock_write(token=branch_token)
         finally:
             branch.repository.unlock()
     except errors.TokenMismatch:
         return FailedSmartServerResponse(('TokenMismatch', ))
     if repo_token:
         branch.repository.dont_leave_lock_in_place()
     branch.dont_leave_lock_in_place()
     branch.unlock()
     return SuccessfulSmartServerResponse(('ok', ))
Example #22
0
 def do_readlocked_repository_request(self, repository, revno,
         known_pair):
     """Find the revid for a given revno, given a known revno/revid pair.
     
     New in 1.17.
     """
     try:
         found_flag, result = repository.get_rev_id_for_revno(revno, known_pair)
     except errors.RevisionNotPresent, err:
         if err.revision_id != known_pair[1]:
             raise AssertionError(
                 'get_rev_id_for_revno raised RevisionNotPresent for '
                 'non-initial revision: ' + err.revision_id)
         return FailedSmartServerResponse(
             ('nosuchrevision', err.revision_id))
Example #23
0
 def do(self, path):
     """try to open a branch at path and return ok/nobranch.
     
     If a bzrdir is not present, an exception is propogated
     rather than 'no branch' because these are different conditions.
     """
     bzrdir = BzrDir.open_from_transport(
         self.transport_from_client_path(path))
     try:
         reference_url = bzrdir.get_branch_reference()
         if reference_url is None:
             return SuccessfulSmartServerResponse(('ok', ''))
         else:
             return SuccessfulSmartServerResponse(('ok', reference_url))
     except errors.NotBranchError:
         return FailedSmartServerResponse(('nobranch', ))
Example #24
0
 def do_repository_request(self, repository, lock_token,
         write_group_tokens):
     """Commit a write group."""
     repository.lock_write(token=lock_token)
     try:
         try:
             repository.resume_write_group(write_group_tokens)
         except errors.UnresumableWriteGroup, e:
             return FailedSmartServerResponse(
                 ('UnresumableWriteGroup', e.write_groups, e.reason))
         try:
             repository.commit_write_group()
         except:
             write_group_tokens = repository.suspend_write_group()
             # FIXME JRV 2011-11-19: What if the write_group_tokens
             # have changed?
             raise
Example #25
0
    def do_repository_request(self, repository, revision_id):
        """Return ok if a signature is present for a revision.

        Introduced in bzr 2.5.0.

        :param repository: The repository to query in.
        :param revision_id: The utf8 encoded revision_id to lookup.
        :return: A smart server response of ('yes', ) if a
            signature for the revision is present,
            ('no', ) if it is missing.
        """
        try:
            if repository.has_signature_for_revision_id(revision_id):
                return SuccessfulSmartServerResponse(('yes', ))
            else:
                return SuccessfulSmartServerResponse(('no', ))
        except errors.NoSuchRevision:
            return FailedSmartServerResponse(
                ('nosuchrevision', revision_id))
Example #26
0
    def do_repository_request(self, repository, to_network_name):
        """Get a stream for inserting into a to_format repository.

        The request body is 'search_bytes', a description of the revisions
        being requested.

        In 2.3 this verb added support for search_bytes == 'everything'.  Older
        implementations will respond with a BadSearch error, and clients should
        catch this and fallback appropriately.

        :param repository: The repository to stream from.
        :param to_network_name: The network name of the format of the target
            repository.
        """
        self._to_format = network_format_registry.get(to_network_name)
        if self._should_fake_unknown():
            return FailedSmartServerResponse(
                ('UnknownMethod', 'Repository.get_stream'))
        return None # Signal that we want a body.
Example #27
0
    def do_repository_request(self, repository, revid, committers):
        """Return the result of repository.gather_stats().

        :param repository: The repository to query in.
        :param revid: utf8 encoded rev id or an empty string to indicate None
        :param committers: 'yes' or 'no'.

        :return: A SmartServerResponse ('ok',), a encoded body looking like
              committers: 1
              firstrev: 1234.230 0
              latestrev: 345.700 3600
              revisions: 2

              But containing only fields returned by the gather_stats() call
        """
        if revid == '':
            decoded_revision_id = None
        else:
            decoded_revision_id = revid
        if committers == 'yes':
            decoded_committers = True
        else:
            decoded_committers = None
        try:
            stats = repository.gather_stats(decoded_revision_id,
                decoded_committers)
        except errors.NoSuchRevision:
            return FailedSmartServerResponse(('nosuchrevision', revid))

        body = ''
        if stats.has_key('committers'):
            body += 'committers: %d\n' % stats['committers']
        if stats.has_key('firstrev'):
            body += 'firstrev: %.3f %d\n' % stats['firstrev']
        if stats.has_key('latestrev'):
             body += 'latestrev: %.3f %d\n' % stats['latestrev']
        if stats.has_key('revisions'):
            body += 'revisions: %d\n' % stats['revisions']
        if stats.has_key('size'):
            body += 'size: %d\n' % stats['size']

        return SuccessfulSmartServerResponse(('ok', ), body)
Example #28
0
    def do(self, path):
        """try to find a repository from path upwards

        This operates precisely like 'bzrdir.find_repository'.

        If a bzrdir is not present, an exception is propagated
        rather than 'no branch' because these are different conditions.

        This is the initial version of this method introduced with the smart
        server. Modern clients will try the V2 method that adds support for the
        supports_external_lookups attribute.

        :return: norepository or ok, relpath.
        """
        try:
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
            return SuccessfulSmartServerResponse(
                ('ok', path, rich_root, tree_ref))
        except errors.NoRepositoryPresent:
            return FailedSmartServerResponse(('norepository', ))
Example #29
0
    def do(self, path):
        """try to find a repository from path upwards

        This operates precisely like 'bzrdir.find_repository'.

        If a bzrdir is not present, an exception is propogated
        rather than 'no branch' because these are different conditions.

        This is the third edition of this method introduced in bzr 1.13, which
        returns information about the network name of the repository format.

        :return: norepository or ok, relpath, rich_root, tree_ref,
            external_lookup, network_name.
        """
        try:
            path, rich_root, tree_ref, external_lookup, name = self._find(path)
            return SuccessfulSmartServerResponse(
                ('ok', path, rich_root, tree_ref, external_lookup, name))
        except errors.NoRepositoryPresent:
            return FailedSmartServerResponse(('norepository', ))
Example #30
0
    def recreate_search(self, repository, search_bytes, discard_excess=False):
        """Recreate a search from its serialised form.

        :param discard_excess: If True, and the search refers to data we don't
            have, just silently accept that fact - the verb calling
            recreate_search trusts that clients will look for missing things
            they expected and get it from elsewhere.
        """
        if search_bytes == 'everything':
            return vf_search.EverythingResult(repository), None
        lines = search_bytes.split('\n')
        if lines[0] == 'ancestry-of':
            heads = lines[1:]
            search_result = vf_search.PendingAncestryResult(heads, repository)
            return search_result, None
        elif lines[0] == 'search':
            return self.recreate_search_from_recipe(repository, lines[1:],
                discard_excess=discard_excess)
        else:
            return (None, FailedSmartServerResponse(('BadSearch',)))