'Handle the head of a \'git-upload-pack\' request.
:param proto: Protocol object to read from
:param capabilities: List of negotiated capabilities
:param graph_walker: GraphWalker instance to call .ack() on
:param wants: List of commits to fetch
:param can_read: function that returns a boolean that indicates
whether there is extra graph data to read on proto'

def _handle_upload_pack_head(self, proto, capabilities, graph_walker, wants, can_read):

    assert (isinstance(wants, list) and isinstance(wants[0], bytes))
    proto.write_pkt_line((((((COMMAND_WANT + '    ') + wants[0]) + '    ') + '    '.join(capabilities)) + '\n'))
    for want in wants[1:]:
        proto.write_pkt_line((((COMMAND_WANT + '    ') + want) + '\n'))
    proto.write_pkt_line(None)
    have = next(graph_walker)
    while have:
        proto.write_pkt_line((((COMMAND_HAVE + '    ') + have) + '\n'))
        if can_read():
            pkt = proto.read_pkt_line()
            parts = pkt.rstrip('\n').split('    ')
            if (parts[0] == 'ACK'):
                graph_walker.ack(parts[1])
                if (parts[2] in ('continue', 'common')):
                    pass
                elif (parts[2] == 'ready'):
                    break
                else:
                    raise AssertionError(("%s    not    in    ('continue',    'ready',    'common)" % parts[2]))
        have = next(graph_walker)
    proto.write_pkt_line((COMMAND_DONE + '\n'))
