'Retrieve a pack from a git smart server.
:param determine_wants: Callback that returns list of commits 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):

    url = self._get_url(path)
    (refs, server_capabilities) = self._discover_references('git-upload-pack', url)
    (negotiated_capabilities, symrefs, agent) = self._negotiate_upload_pack_capabilities(server_capabilities)
    wants = determine_wants(refs)
    if (wants is not None):
        wants = [cid for cid in wants if (cid != ZERO_SHA)]
    if (not wants):
        return FetchPackResult(refs, symrefs, agent)
    if self.dumb:
        raise NotImplementedError(self.send_pack)
    req_data = BytesIO()
    req_proto = Protocol(None, req_data.write)
    self._handle_upload_pack_head(req_proto, negotiated_capabilities, graph_walker, wants, (lambda : False))
    resp = self._smart_request('git-upload-pack', url, data=req_data.getvalue())
    try:
        resp_proto = Protocol(resp.read, None)
        self._handle_upload_pack_tail(resp_proto, negotiated_capabilities, graph_walker, pack_data, progress)
        return FetchPackResult(refs, symrefs, agent)
    finally:
        resp.close()
