CAPABILITY_OFS_DELTA,
CAPABILITY_QUIET,
CAPABILITY_REPORT_STATUS,
+ CAPABILITY_SHALLOW,
CAPABILITY_SYMREF,
CAPABILITY_SIDE_BAND_64K,
CAPABILITY_THIN_PACK,
CAPABILITIES_REF,
KNOWN_RECEIVE_CAPABILITIES,
KNOWN_UPLOAD_CAPABILITIES,
+ COMMAND_DEEPEN,
COMMAND_DONE,
COMMAND_HAVE,
COMMAND_WANT,
COMMON_CAPABILITIES = [CAPABILITY_OFS_DELTA, CAPABILITY_SIDE_BAND_64K]
UPLOAD_CAPABILITIES = ([CAPABILITY_THIN_PACK, CAPABILITY_MULTI_ACK,
- CAPABILITY_MULTI_ACK_DETAILED] + COMMON_CAPABILITIES)
+ CAPABILITY_MULTI_ACK_DETAILED, CAPABILITY_SHALLOW]
+ + COMMON_CAPABILITIES)
RECEIVE_CAPABILITIES = [CAPABILITY_REPORT_STATUS] + COMMON_CAPABILITIES
"""
raise NotImplementedError(self.send_pack)
- def fetch(self, path, target, determine_wants=None, progress=None):
+ def fetch(self, path, target, determine_wants=None, progress=None,
+ depth=None):
"""Fetch into a target repository.
:param path: Path to fetch from (as bytestring)
to fetch. Receives dictionary of name->sha, should return
list of shas to fetch. Defaults to all shas.
:param progress: Optional progress function
+ :param depth: Depth to fetch at
:return: Dictionary with all remote refs (not just those fetched)
"""
if determine_wants is None:
try:
result = self.fetch_pack(
path, determine_wants, target.get_graph_walker(), f.write,
- progress)
+ progress=progress, depth=depth)
except BaseException:
abort()
raise
return (negotiated_capabilities, symrefs, agent)
def _handle_upload_pack_head(self, proto, capabilities, graph_walker,
- wants, can_read):
+ wants, can_read, depth):
"""Handle the head of a 'git-upload-pack' request.
:param proto: Protocol object to read from
: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
+ :param depth: Depth for request
"""
assert isinstance(wants, list) and isinstance(wants[0], bytes)
proto.write_pkt_line(COMMAND_WANT + b' ' + wants[0] + b' ' +
b' '.join(capabilities) + b'\n')
for want in wants[1:]:
proto.write_pkt_line(COMMAND_WANT + b' ' + want + b'\n')
+ if depth not in (0, None):
+ if not CAPABILITY_SHALLOW in capabilities:
+ raise GitProtocolError(
+ "server does not support shallow capability required for "
+ "depth")
+ proto.write_pkt_line(b'%s %d\n' % (COMMAND_DEEPEN, depth))
proto.write_pkt_line(None)
have = next(graph_walker)
while have:
return new_refs
def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
- progress=None):
+ depth=None, progress=None):
"""Retrieve a pack from a git smart server.
:param path: Remote path to fetch from
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 depth: Depth for request
:param progress: Callback for progress reports (strings)
:return: FetchPackResult object
"""
return FetchPackResult(refs, symrefs, agent)
check_wants(wants, refs)
self._handle_upload_pack_head(
- proto, negotiated_capabilities, graph_walker, wants, can_read)
+ proto, negotiated_capabilities, graph_walker, wants, can_read,
+ depth=depth)
self._handle_upload_pack_tail(
proto, negotiated_capabilities, graph_walker, pack_data,
progress)
resp.close()
def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
- progress=None):
+ depth=None, progress=None):
"""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)
+ :param depth: Depth for request
:return: FetchPackResult object
"""
url = self._get_url(path)
req_proto = Protocol(None, req_data.write)
self._handle_upload_pack_head(
req_proto, negotiated_capabilities, graph_walker, wants,
- lambda: False)
+ lambda: False, depth=depth)
resp, read = self._smart_request(
"git-upload-pack", url, data=req_data.getvalue())
try:
def clone(source, target=None, bare=False, checkout=None,
errstream=default_bytes_err_stream, outstream=None,
- origin=b"origin", **kwargs):
+ origin=b"origin", depth=None, **kwargs):
"""Clone a local or remote git repository.
:param source: Path or URL for source repository
:param errstream: Optional stream to write progress to
:param outstream: Optional stream to write progress to (deprecated)
:param origin: Name of remote from the repository used to clone
+ :param depth: Depth to fetch at
:return: The new repository
"""
# TODO(jelmer): This code overlaps quite a bit with Repo.clone
try:
fetch_result = fetch(
r, source, origin, errstream=errstream, message=reflog_message,
- **kwargs)
+ depth=depth, **kwargs)
target_config = r.get_config()
if not isinstance(source, bytes):
source = source.encode(DEFAULT_ENCODING)
def fetch(repo, remote_location, remote_name=b'origin', outstream=sys.stdout,
- errstream=default_bytes_err_stream, message=None, **kwargs):
+ errstream=default_bytes_err_stream, message=None, depth=None, **kwargs):
"""Fetch objects from a remote server.
:param repo: Path to the repository
:param outstream: Output stream (defaults to stdout)
:param errstream: Error stream (defaults to stderr)
:param message: Reflog message (defaults to b"fetch: from <remote_name>")
+ :param depth: Depth to fetch at
:return: Dictionary with refs on the remote
"""
if message is None:
with open_repo_closing(repo) as r:
client, path = get_transport_and_path(
remote_location, config=r.get_config_stack(), **kwargs)
- fetch_result = client.fetch(path, r, progress=errstream.write)
+ fetch_result = client.fetch(path, r, progress=errstream.write,
+ depth=depth)
stripped_refs = strip_peeled_refs(fetch_result.refs)
branches = {
n[len(b'refs/heads/'):]: v for (n, v) in stripped_refs.items()