'Retrieve a pack from a git smart server.
:param path: Remote path to fetch from
:param determine_wants: Function determine what refs
to fetch. Receives dictionary of name->sha, should return
list of shas to fetch.
:param graph_walker: Object with next() and ack().
:param pack_data: Callback called for each bit of data in the pack
:param progress: Callback for progress reports (strings)
:return: FetchPackResult object'

def fetch_pack(self, path, determine_wants, graph_walker, pack_data, progress=None):

    (proto, can_read) = self._connect('upload-pack', path)
    with proto:
        (refs, server_capabilities) = read_pkt_refs(proto)
        (negotiated_capabilities, symrefs, agent) = self._negotiate_upload_pack_capabilities(server_capabilities)
        if (refs is None):
            proto.write_pkt_line(None)
            return FetchPackResult(refs, symrefs, agent)
        try:
            wants = determine_wants(refs)
        except:
            proto.write_pkt_line(None)
            raise
        if (wants is not None):
            wants = [cid for cid in wants if (cid != ZERO_SHA)]
        if (not wants):
            proto.write_pkt_line(None)
            return FetchPackResult(refs, symrefs, agent)
        self._handle_upload_pack_head(proto, negotiated_capabilities, graph_walker, wants, can_read)
        self._handle_upload_pack_tail(proto, negotiated_capabilities, graph_walker, pack_data, progress)
        return FetchPackResult(refs, symrefs, agent)
