Ejemplo n.º 1
0
 def test_ack_type(self):
     self.assertEqual(SINGLE_ACK, ack_type([b'foo', b'bar']))
     self.assertEqual(MULTI_ACK, ack_type([b'foo', b'bar', b'multi_ack']))
     self.assertEqual(MULTI_ACK_DETAILED,
                       ack_type([b'foo', b'bar', b'multi_ack_detailed']))
     # choose detailed when both present
     self.assertEqual(MULTI_ACK_DETAILED,
                       ack_type([b'foo', b'bar', b'multi_ack',
                                 b'multi_ack_detailed']))
Ejemplo n.º 2
0
 def test_ack_type(self):
     self.assertEquals(SINGLE_ACK, ack_type(['foo', 'bar']))
     self.assertEquals(MULTI_ACK, ack_type(['foo', 'bar', 'multi_ack']))
     self.assertEquals(MULTI_ACK_DETAILED,
                       ack_type(['foo', 'bar', 'multi_ack_detailed']))
     # choose detailed when both present
     self.assertEquals(
         MULTI_ACK_DETAILED,
         ack_type(['foo', 'bar', 'multi_ack', 'multi_ack_detailed']))
Ejemplo n.º 3
0
 def test_ack_type(self):
     self.assertEqual(SINGLE_ACK, ack_type([b"foo", b"bar"]))
     self.assertEqual(MULTI_ACK, ack_type([b"foo", b"bar", b"multi_ack"]))
     self.assertEqual(
         MULTI_ACK_DETAILED,
         ack_type([b"foo", b"bar", b"multi_ack_detailed"]),
     )
     # choose detailed when both present
     self.assertEqual(
         MULTI_ACK_DETAILED,
         ack_type([b"foo", b"bar", b"multi_ack", b"multi_ack_detailed"]),
     )
Ejemplo n.º 4
0
    def determine_wants(self, heads):
        """Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs he wants using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        :param heads: a dict of refname->SHA1 to advertise
        :return: a list of SHA1s requested by the client
        """
        if not heads:
            # The repo is empty, so short-circuit the whole process.
            self.proto.write_pkt_line(None)
            return []
        values = set(heads.itervalues())
        if self.advertise_refs or not self.http_req:
            for i, (ref, sha) in enumerate(sorted(heads.iteritems())):
                line = "%s %s" % (sha, ref)
                if not i:
                    line = "%s\x00%s" % (line, self.handler.capability_line())
                self.proto.write_pkt_line("%s\n" % line)
                peeled_sha = self.get_peeled(ref)
                if peeled_sha != sha:
                    self.proto.write_pkt_line('%s %s^{}\n' %
                                              (peeled_sha, ref))

            # i'm done..
            self.proto.write_pkt_line(None)

            if self.advertise_refs:
                return None

        # Now client will sending want want want commands
        want = self.proto.read_pkt_line()
        if not want:
            return []
        line, caps = extract_want_line_capabilities(want)
        self.handler.set_client_capabilities(caps)
        self.set_ack_type(ack_type(caps))
        allowed = ('want', None)
        command, sha = _split_proto_line(line, allowed)

        want_revs = []
        while command != None:
            if sha not in values:
                raise GitProtocolError(
                  'Client wants invalid object %s' % sha)
            want_revs.append(sha)
            command, sha = self.read_proto_line(allowed)

        self.set_wants(want_revs)

        if self.http_req and self.proto.eof():
            # The client may close the socket at this point, expecting a
            # flush-pkt from the server. We might be ready to send a packfile at
            # this point, so we need to explicitly short-circuit in this case.
            return []

        return want_revs
Ejemplo n.º 5
0
    def determine_wants(self, heads):
        """Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs he wants using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        :param heads: a dict of refname->SHA1 to advertise
        :return: a list of SHA1s requested by the client
        """
        if not heads:
            # The repo is empty, so short-circuit the whole process.
            self.proto.write_pkt_line(None)
            return None
        values = set(heads.itervalues())
        if self.advertise_refs or not self.http_req:
            for i, (ref, sha) in enumerate(sorted(heads.iteritems())):
                line = "%s %s" % (sha, ref)
                if not i:
                    line = "%s\x00%s" % (line, self.handler.capability_line())
                self.proto.write_pkt_line("%s\n" % line)
                peeled_sha = self.get_peeled(ref)
                if peeled_sha != sha:
                    self.proto.write_pkt_line('%s %s^{}\n' % (peeled_sha, ref))

            # i'm done..
            self.proto.write_pkt_line(None)

            if self.advertise_refs:
                return None

        # Now client will sending want want want commands
        want = self.proto.read_pkt_line()
        if not want:
            return []
        line, caps = extract_want_line_capabilities(want)
        self.handler.set_client_capabilities(caps)
        self.set_ack_type(ack_type(caps))
        allowed = ('want', None)
        command, sha = _split_proto_line(line, allowed)

        want_revs = []
        while command != None:
            if sha not in values:
                raise GitProtocolError('Client wants invalid object %s' % sha)
            want_revs.append(sha)
            command, sha = self.read_proto_line(allowed)

        self.set_wants(want_revs)

        if self.http_req and self.proto.eof():
            # The client may close the socket at this point, expecting a
            # flush-pkt from the server. We might be ready to send a packfile at
            # this point, so we need to explicitly short-circuit in this case.
            return None

        return want_revs
Ejemplo n.º 6
0
    def determine_wants(self, heads):
        """Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs he wants using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        :param heads: a dict of refname->SHA1 to advertise
        :return: a list of SHA1s requested by the client
        """
        if not heads:
            raise GitProtocolError('No heads found')
        values = set(heads.itervalues())
        if self.advertise_refs or not self.stateless_rpc:
            for i, (ref, sha) in enumerate(heads.iteritems()):
                line = "%s %s" % (sha, ref)
                if not i:
                    line = "%s\x00%s" % (line, self.handler.capabilities())
                self.proto.write_pkt_line("%s\n" % line)
                # TODO: include peeled value of any tags

            # i'm done..
            self.proto.write_pkt_line(None)

            if self.advertise_refs:
                return []

        # Now client will sending want want want commands
        want = self.proto.read_pkt_line()
        if not want:
            return []
        line, caps = extract_want_line_capabilities(want)
        self.handler.client_capabilities = caps
        self.set_ack_type(ack_type(caps))
        command, sha = self._split_proto_line(line)

        want_revs = []
        while command != None:
            if command != 'want':
                raise GitProtocolError(
                    'Protocol got unexpected command %s' % command)
            if sha not in values:
                raise GitProtocolError(
                    'Client wants invalid object %s' % sha)
            want_revs.append(sha)
            command, sha = self.read_proto_line()

        self.set_wants(want_revs)
        return want_revs
Ejemplo n.º 7
0
    def determine_wants(self, heads):
        """Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs he wants using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        If the client has the 'shallow' capability, this method also reads and
        responds to the 'shallow' and 'deepen' lines from the client. These are
        not part of the wants per se, but they set up necessary state for
        walking the graph. Additionally, later code depends on this method
        consuming everything up to the first 'have' line.

        :param heads: a dict of refname->SHA1 to advertise
        :return: a list of SHA1s requested by the client
        """
        values = set(heads.itervalues())
        if self.advertise_refs or not self.http_req:
            for i, (ref, sha) in enumerate(sorted(heads.iteritems())):
                line = "%s %s" % (sha, ref)
                if not i:
                    line = "%s\x00%s" % (line, self.handler.capability_line())
                self.proto.write_pkt_line("%s\n" % line)
                peeled_sha = self.get_peeled(ref)
                if peeled_sha != sha:
                    self.proto.write_pkt_line('%s %s^{}\n' %
                                              (peeled_sha, ref))

            # i'm done..
            self.proto.write_pkt_line(None)

            if self.advertise_refs:
                return []

        # Now client will sending want want want commands
        want = self.proto.read_pkt_line()
        if not want:
            return []
        line, caps = extract_want_line_capabilities(want)
        self.handler.set_client_capabilities(caps)
        self.set_ack_type(ack_type(caps))
        allowed = ('want', 'shallow', 'deepen', None)
        command, sha = _split_proto_line(line, allowed)

        want_revs = []
        while command == 'want':
            if sha not in values:
                raise GitProtocolError(
                  'Client wants invalid object %s' % sha)
            want_revs.append(sha)
            command, sha = self.read_proto_line(allowed)

        self.set_wants(want_revs)
        if command in ('shallow', 'deepen'):
            self.unread_proto_line(command, sha)
            self._handle_shallow_request(want_revs)

        if self.http_req and self.proto.eof():
            # The client may close the socket at this point, expecting a
            # flush-pkt from the server. We might be ready to send a packfile at
            # this point, so we need to explicitly short-circuit in this case.
            return []

        return want_revs
Ejemplo n.º 8
0
    def determine_wants(self, heads):
        """Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs he wants using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        If the client has the 'shallow' capability, this method also reads and
        responds to the 'shallow' and 'deepen' lines from the client. These are
        not part of the wants per se, but they set up necessary state for
        walking the graph. Additionally, later code depends on this method
        consuming everything up to the first 'have' line.

        :param heads: a dict of refname->SHA1 to advertise
        :return: a list of SHA1s requested by the client
        """
        values = set(heads.values())
        if self.advertise_refs or not self.http_req:
            for i, (ref, sha) in enumerate(sorted(heads.items())):
                line = sha + b' ' + ref
                if not i:
                    line += b'\x00' + self.handler.capability_line()
                self.proto.write_pkt_line(line + b'\n')
                peeled_sha = self.get_peeled(ref)
                if peeled_sha != sha:
                    self.proto.write_pkt_line(peeled_sha + b' ' + ref + b'^{}\n')

            # i'm done..
            self.proto.write_pkt_line(None)

            if self.advertise_refs:
                return []

        # Now client will sending want want want commands
        want = self.proto.read_pkt_line()
        if not want:
            return []
        line, caps = extract_want_line_capabilities(want)
        self.handler.set_client_capabilities(caps)
        self.set_ack_type(ack_type(caps))
        allowed = (COMMAND_WANT, COMMAND_SHALLOW, COMMAND_DEEPEN, None)
        command, sha = _split_proto_line(line, allowed)

        want_revs = []
        while command == COMMAND_WANT:
            if sha not in values:
                raise GitProtocolError(
                  'Client wants invalid object %s' % sha)
            want_revs.append(sha)
            command, sha = self.read_proto_line(allowed)

        self.set_wants(want_revs)
        if command in (COMMAND_SHALLOW, COMMAND_DEEPEN):
            self.unread_proto_line(command, sha)
            self._handle_shallow_request(want_revs)

        if self.http_req and self.proto.eof():
            # The client may close the socket at this point, expecting a
            # flush-pkt from the server. We might be ready to send a packfile at
            # this point, so we need to explicitly short-circuit in this case.
            return []

        return want_revs
Ejemplo n.º 9
0
    def determine_wants(self, heads):
        """Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs he wants using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        If the client has the 'shallow' capability, this method also reads and
        responds to the 'shallow' and 'deepen' lines from the client. These are
        not part of the wants per se, but they set up necessary state for
        walking the graph. Additionally, later code depends on this method
        consuming everything up to the first 'have' line.

        :param heads: a dict of refname->SHA1 to advertise
        :return: a list of SHA1s requested by the client
        """
        symrefs = self.get_symrefs()
        values = set(heads.values())
        if self.advertise_refs or not self.http_req:
            for i, (ref, sha) in enumerate(sorted(heads.items())):
                try:
                    peeled_sha = self.get_peeled(ref)
                except KeyError:
                    # Skip refs that are inaccessible
                    # TODO(jelmer): Integrate with Repo.fetch_objects refs
                    # logic.
                    continue
                line = sha + b' ' + ref
                if not i:
                    line += (b'\x00' +
                             self.handler.capability_line(
                                 self.handler.capabilities() +
                                 symref_capabilities(symrefs.items())))
                self.proto.write_pkt_line(line + b'\n')
                if peeled_sha != sha:
                    self.proto.write_pkt_line(
                        peeled_sha + b' ' + ref + ANNOTATED_TAG_SUFFIX + b'\n')

            # i'm done..
            self.proto.write_pkt_line(None)

            if self.advertise_refs:
                return []

        # Now client will sending want want want commands
        want = self.proto.read_pkt_line()
        if not want:
            return []
        line, caps = extract_want_line_capabilities(want)
        self.handler.set_client_capabilities(caps)
        self.set_ack_type(ack_type(caps))
        allowed = (COMMAND_WANT, COMMAND_SHALLOW, COMMAND_DEEPEN, None)
        command, sha = _split_proto_line(line, allowed)

        want_revs = []
        while command == COMMAND_WANT:
            if sha not in values:
                raise GitProtocolError(
                  'Client wants invalid object %s' % sha)
            want_revs.append(sha)
            command, sha = self.read_proto_line(allowed)

        self.set_wants(want_revs)
        if command in (COMMAND_SHALLOW, COMMAND_DEEPEN):
            self.unread_proto_line(command, sha)
            self._handle_shallow_request(want_revs)

        if self.http_req and self.proto.eof():
            # The client may close the socket at this point, expecting a
            # flush-pkt from the server. We might be ready to send a packfile
            # at this point, so we need to explicitly short-circuit in this
            # case.
            return []

        return want_revs
Ejemplo n.º 10
0
    def determine_wants(self, heads):
        """Determine the wants for a set of heads.

        The given heads are advertised to the client, who then specifies which
        refs they want using 'want' lines. This portion of the protocol is the
        same regardless of ack type, and in fact is used to set the ack type of
        the ProtocolGraphWalker.

        If the client has the 'shallow' capability, this method also reads and
        responds to the 'shallow' and 'deepen' lines from the client. These are
        not part of the wants per se, but they set up necessary state for
        walking the graph. Additionally, later code depends on this method
        consuming everything up to the first 'have' line.

        Args:
          heads: a dict of refname->SHA1 to advertise
        Returns: a list of SHA1s requested by the client
        """
        symrefs = self.get_symrefs()
        values = set(heads.values())
        if self.advertise_refs or not self.stateless_rpc:
            for i, (ref, sha) in enumerate(sorted(heads.items())):
                try:
                    peeled_sha = self.get_peeled(ref)
                except KeyError:
                    # Skip refs that are inaccessible
                    # TODO(jelmer): Integrate with Repo.fetch_objects refs
                    # logic.
                    continue
                line = sha + b" " + ref
                if not i:
                    line += b"\x00" + self.handler.capability_line(
                        self.handler.capabilities() +
                        symref_capabilities(symrefs.items()))
                self.proto.write_pkt_line(line + b"\n")
                if peeled_sha != sha:
                    self.proto.write_pkt_line(peeled_sha + b" " + ref +
                                              ANNOTATED_TAG_SUFFIX + b"\n")

            # i'm done..
            self.proto.write_pkt_line(None)

            if self.advertise_refs:
                return []

        # Now client will sending want want want commands
        want = self.proto.read_pkt_line()
        if not want:
            return []
        line, caps = extract_want_line_capabilities(want)
        self.handler.set_client_capabilities(caps)
        self.set_ack_type(ack_type(caps))
        allowed = (COMMAND_WANT, COMMAND_SHALLOW, COMMAND_DEEPEN, None)
        command, sha = _split_proto_line(line, allowed)

        want_revs = []
        while command == COMMAND_WANT:
            if sha not in values:
                raise GitProtocolError("Client wants invalid object %s" % sha)
            want_revs.append(sha)
            command, sha = self.read_proto_line(allowed)

        self.set_wants(want_revs)
        if command in (COMMAND_SHALLOW, COMMAND_DEEPEN):
            self.unread_proto_line(command, sha)
            self._handle_shallow_request(want_revs)

        if self.stateless_rpc and self.proto.eof():
            # The client may close the socket at this point, expecting a
            # flush-pkt from the server. We might be ready to send a packfile
            # at this point, so we need to explicitly short-circuit in this
            # case.
            return []

        return want_revs