|
@@ -42,7 +42,6 @@ from contextlib import closing
|
|
|
from io import BytesIO, BufferedReader
|
|
|
import dulwich
|
|
|
import select
|
|
|
-import shlex
|
|
|
import socket
|
|
|
import subprocess
|
|
|
import sys
|
|
@@ -230,12 +229,20 @@ class GitClient(object):
|
|
|
:param determine_wants: Optional function to determine what refs
|
|
|
to fetch
|
|
|
:param progress: Optional progress function
|
|
|
- :return: remote refs as dictionary
|
|
|
+ :return: Dictionary with all remote refs (not just those fetched)
|
|
|
"""
|
|
|
if determine_wants is None:
|
|
|
determine_wants = target.object_store.determine_wants_all
|
|
|
-
|
|
|
- f, commit, abort = target.object_store.add_pack()
|
|
|
+ if CAPABILITY_THIN_PACK in self._fetch_capabilities:
|
|
|
+ # TODO(jelmer): Avoid reading entire file into memory and
|
|
|
+ # only processing it after the whole file has been fetched.
|
|
|
+ f = BytesIO()
|
|
|
+ def commit():
|
|
|
+ if f.tell():
|
|
|
+ f.seek(0)
|
|
|
+ target.object_store.add_thin_pack(f.read, None)
|
|
|
+ else:
|
|
|
+ f, commit, abort = target.object_store.add_pack()
|
|
|
try:
|
|
|
result = self.fetch_pack(
|
|
|
path, determine_wants, target.get_graph_walker(), f.write,
|
|
@@ -255,6 +262,7 @@ class GitClient(object):
|
|
|
: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: Dictionary with all remote refs (not just those fetched)
|
|
|
"""
|
|
|
raise NotImplementedError(self.fetch_pack)
|
|
|
|
|
@@ -542,6 +550,7 @@ class TraditionalGitClient(GitClient):
|
|
|
: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: Dictionary with all remote refs (not just those fetched)
|
|
|
"""
|
|
|
proto, can_read = self._connect(b'upload-pack', path)
|
|
|
with proto:
|
|
@@ -662,7 +671,7 @@ class SubprocessWrapper(object):
|
|
|
self.write = proc.stdin.write
|
|
|
|
|
|
def can_read(self):
|
|
|
- if subprocess.mswindows:
|
|
|
+ if sys.platform == 'win32':
|
|
|
from msvcrt import get_osfhandle
|
|
|
from win32pipe import PeekNamedPipe
|
|
|
handle = get_osfhandle(self.proc.stdout.fileno())
|
|
@@ -784,7 +793,7 @@ class LocalGitClient(GitClient):
|
|
|
:param determine_wants: Optional function to determine what refs
|
|
|
to fetch
|
|
|
:param progress: Optional progress function
|
|
|
- :return: remote refs as dictionary
|
|
|
+ :return: Dictionary with all remote refs (not just those fetched)
|
|
|
"""
|
|
|
from dulwich.repo import Repo
|
|
|
with closing(Repo(path)) as r:
|
|
@@ -799,6 +808,7 @@ class LocalGitClient(GitClient):
|
|
|
: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: Dictionary with all remote refs (not just those fetched)
|
|
|
"""
|
|
|
from dulwich.repo import Repo
|
|
|
with closing(Repo(path)) as r:
|
|
@@ -850,8 +860,7 @@ class SubprocessSSHVendor(SSHVendor):
|
|
|
"""SSH vendor that shells out to the local 'ssh' command."""
|
|
|
|
|
|
def run_command(self, host, command, username=None, port=None):
|
|
|
- if (type(command) is not list or
|
|
|
- not all([isinstance(b, bytes) for b in command])):
|
|
|
+ if not isinstance(command, bytes):
|
|
|
raise TypeError(command)
|
|
|
|
|
|
#FIXME: This has no way to deal with passwords..
|
|
@@ -861,7 +870,7 @@ class SubprocessSSHVendor(SSHVendor):
|
|
|
if username is not None:
|
|
|
host = '%s@%s' % (username, host)
|
|
|
args.append(host)
|
|
|
- proc = subprocess.Popen(args + command,
|
|
|
+ proc = subprocess.Popen(args + [command],
|
|
|
stdin=subprocess.PIPE,
|
|
|
stdout=subprocess.PIPE)
|
|
|
return SubprocessWrapper(proc)
|
|
@@ -896,11 +905,7 @@ class SSHGitClient(TraditionalGitClient):
|
|
|
def _get_cmd_path(self, cmd):
|
|
|
cmd = self.alternative_paths.get(cmd, b'git-' + cmd)
|
|
|
assert isinstance(cmd, bytes)
|
|
|
- if sys.version_info[:2] <= (2, 6):
|
|
|
- return shlex.split(cmd)
|
|
|
- else:
|
|
|
- # TODO(jelmer): Don't decode/encode here
|
|
|
- return [x.encode('ascii') for x in shlex.split(cmd.decode('ascii'))]
|
|
|
+ return cmd
|
|
|
|
|
|
def _connect(self, cmd, path):
|
|
|
if type(cmd) is not bytes:
|
|
@@ -909,7 +914,7 @@ class SSHGitClient(TraditionalGitClient):
|
|
|
raise TypeError(path)
|
|
|
if path.startswith(b"/~"):
|
|
|
path = path[1:]
|
|
|
- argv = self._get_cmd_path(cmd) + [path]
|
|
|
+ argv = self._get_cmd_path(cmd) + b" '" + path + b"'"
|
|
|
con = self.ssh_vendor.run_command(
|
|
|
self.host, argv, port=self.port, username=self.username)
|
|
|
return (Protocol(con.read, con.write, con.close,
|
|
@@ -1057,7 +1062,7 @@ class HttpGitClient(GitClient):
|
|
|
: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: Dictionary with the refs of the remote repository
|
|
|
+ :return: Dictionary with all remote refs (not just those fetched)
|
|
|
"""
|
|
|
url = self._get_url(path)
|
|
|
refs, server_capabilities = self._discover_references(
|