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']))
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']))
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"]), )
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
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
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
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
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
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
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