Пример #1
0
    def handle(self) -> None:
        if self.advertise_refs or not self.stateless_rpc:
            refs = sorted(self.repo.get_refs().items())
            symrefs = sorted(self.repo.refs.get_symrefs().items())

            if not refs:
                refs = [(CAPABILITIES_REF, ZERO_SHA)]
            self.proto.write_pkt_line(
                refs[0][1]
                + b" "
                + refs[0][0]
                + b"\0"
                + self.capability_line(
                    self.capabilities() + symref_capabilities(symrefs)
                )
                + b"\n"
            )
            for i in range(1, len(refs)):
                ref = refs[i]
                self.proto.write_pkt_line(ref[1] + b" " + ref[0] + b"\n")

            self.proto.write_pkt_line(None)
            if self.advertise_refs:
                return

        client_refs = []
        ref = self.proto.read_pkt_line()

        # if ref is none then client doesnt want to send us anything..
        if ref is None:
            return

        ref, caps = extract_capabilities(ref)
        self.set_client_capabilities(caps)

        # client will now send us a list of (oldsha, newsha, ref)
        while ref:
            client_refs.append(ref.split())
            ref = self.proto.read_pkt_line()

        # backend can now deal with this refs and read a pack using self.read
        status = self._apply_pack(client_refs)

        self._on_post_receive(client_refs)

        # when we have read all the pack from the client, send a status report
        # if the client asked for it
        if self.has_capability(CAPABILITY_REPORT_STATUS):
            self._report_status(status)
Пример #2
0
    def handle(self):
        if self.advertise_refs or not self.http_req:
            refs = sorted(self.repo.get_refs().items())
            symrefs = sorted(self.repo.refs.get_symrefs().items())

            if not refs:
                refs = [(CAPABILITIES_REF, ZERO_SHA)]
            self.proto.write_pkt_line(
              refs[0][1] + b' ' + refs[0][0] + b'\0' +
              self.capability_line(
                  self.capabilities() + symref_capabilities(symrefs)) + b'\n')
            for i in range(1, len(refs)):
                ref = refs[i]
                self.proto.write_pkt_line(ref[1] + b' ' + ref[0] + b'\n')

            self.proto.write_pkt_line(None)
            if self.advertise_refs:
                return

        client_refs = []
        ref = self.proto.read_pkt_line()

        # if ref is none then client doesnt want to send us anything..
        if ref is None:
            return

        ref, caps = extract_capabilities(ref)
        self.set_client_capabilities(caps)

        # client will now send us a list of (oldsha, newsha, ref)
        while ref:
            client_refs.append(ref.split())
            ref = self.proto.read_pkt_line()

        # backend can now deal with this refs and read a pack using self.read
        status = self._apply_pack(client_refs)

        # when we have read all the pack from the client, send a status report
        # if the client asked for it
        if self.has_capability(CAPABILITY_REPORT_STATUS):
            self._report_status(status)
Пример #3
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(user): 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
Пример #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.

        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