Changeset d67ecb373569…
Parent 7057395ff809…
by
Changes to 2 files · Browse files at d67ecb373569 Showing diff from parent 7057395ff809 Diff from another changeset...
|
|
@@ -24,6 +24,7 @@ import select
import socket
import subprocess
+import urllib2
import urlparse
from dulwich.errors import (
@@ -77,67 +78,6 @@ if thin_packs:
self._fetch_capabilities.append('thin-pack')
- def send_pack(self, path, determine_wants, generate_pack_contents):
- """Upload a pack to a remote repository.
-
- :param path: Repository path
- :param generate_pack_contents: Function that can return a sequence of the
- shas of the objects to upload.
-
- :raises SendPackError: if server rejects the pack data
- :raises UpdateRefsError: if the server supports report-status
- and rejects ref updates
- """
- raise NotImplementedError(self.send_pack)
-
- def fetch(self, path, target, determine_wants=None, progress=None):
- """Fetch into a target repository.
-
- :param path: Path to fetch from
- :param target: Target repository to fetch into
- :param determine_wants: Optional function to determine what refs
- to fetch
- :param progress: Optional progress function
- :return: remote refs
- """
- if determine_wants is None:
- determine_wants = target.object_store.determine_wants_all
- f, commit = target.object_store.add_pack()
- try:
- return self.fetch_pack(path, determine_wants,
- target.get_graph_walker(), f.write, progress)
- finally:
- commit()
-
- def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
- progress):
- """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)
- """
- raise NotImplementedError(self.fetch_pack)
-
-
-class TraditionalGitClient(GitClient):
- """Traditional Git client."""
-
- def _connect(self, cmd, path):
- """Create a connection to the server.
-
- This method is abstract - concrete implementations should
- implement their own variant which connects to the server and
- returns an initialized Protocol object with the service ready
- for use and a can_read function which may be used to see if
- reads would block.
-
- :param cmd: The git service name to which we should connect.
- :param path: The path we should pass to the service.
- """
- raise NotImplementedError()
-
def _read_refs(self, proto):
server_capabilities = None
refs = {}
@@ -150,6 +90,67 @@ (ref, server_capabilities) = extract_capabilities(ref)
refs[ref] = sha
return refs, server_capabilities
+
+ def send_pack(self, path, determine_wants, generate_pack_contents):
+ """Upload a pack to a remote repository.
+
+ :param path: Repository path
+ :param generate_pack_contents: Function that can return a sequence of the
+ shas of the objects to upload.
+
+ :raises SendPackError: if server rejects the pack data
+ :raises UpdateRefsError: if the server supports report-status
+ and rejects ref updates
+ """
+ raise NotImplementedError(self.send_pack)
+
+ def fetch(self, path, target, determine_wants=None, progress=None):
+ """Fetch into a target repository.
+
+ :param path: Path to fetch from
+ :param target: Target repository to fetch into
+ :param determine_wants: Optional function to determine what refs
+ to fetch
+ :param progress: Optional progress function
+ :return: remote refs
+ """
+ if determine_wants is None:
+ determine_wants = target.object_store.determine_wants_all
+ f, commit = target.object_store.add_pack()
+ try:
+ return self.fetch_pack(path, determine_wants,
+ target.get_graph_walker(), f.write, progress)
+ finally:
+ commit()
+
+ def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
+ progress):
+ """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)
+ """
+ raise NotImplementedError(self.fetch_pack)
+
+
+class TraditionalGitClient(GitClient):
+ """Traditional Git client."""
+
+ def _connect(self, cmd, path):
+ """Create a connection to the server.
+
+ This method is abstract - concrete implementations should
+ implement their own variant which connects to the server and
+ returns an initialized Protocol object with the service ready
+ for use and a can_read function which may be used to see if
+ reads would block.
+
+ :param cmd: The git service name to which we should connect.
+ :param path: The path we should pass to the service.
+ """
+ raise NotImplementedError()
def _parse_status_report(self, proto):
unpack = proto.read_pkt_line().strip()
@@ -416,11 +417,16 @@
class HttpGitClient(GitClient):
- def __init__(self, host, port=None, username=None, force_dumb=False, *args, **kwargs):
+ def __init__(self, host, port=None, username=None, password=None, dumb=None, *args, **kwargs):
self.host = host
self.port = port
- self.force_dumb = force_dumb
+ self.dumb = dumb
self.username = username
+ self.password = password
+ netloc = self.host
+ if self.port:
+ netloc += ":%d" % self.port
+ self.url = "http://%s/" % netloc
GitClient.__init__(self, *args, **kwargs)
@classmethod
@@ -428,7 +434,17 @@ parsed = urlparse.urlparse(url)
assert parsed.scheme == 'http'
return cls(parsed.hostname, port=parsed.port, username=parsed.port,
- password=parsed.password)
+ password=parsed.password), parsed.path
+
+ def _discover_references(self, service, url):
+ url = urlparse.urljoin(url+"/", "info/refs")
+ if not self.dumb:
+ url += "?service=%s" % service
+ req = urllib2.Request(url)
+ resp = urllib2.urlopen(req)
+ self.dumb = (not resp.info().gettype().startswith("application/x-git-"))
+ proto = Protocol(resp.read, None, report_activity=self._report_activity)
+ return self._read_refs(proto)
def send_pack(self, path, determine_wants, generate_pack_contents):
"""Upload a pack to a remote repository.
@@ -441,6 +457,8 @@ :raises UpdateRefsError: if the server supports report-status
and rejects ref updates
"""
+ url = urlparse.urljoin(self.url, path)
+ refs, server_capabilities = self._discover_references("git-upload-pack", url)
raise NotImplementedError(self.send_pack)
def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
@@ -452,6 +470,8 @@ :param pack_data: Callback called for each bit of data in the pack
:param progress: Callback for progress reports (strings)
"""
+ url = urlparse.urljoin(self.url, path)
+ refs, server_capabilities = self._discover_references("git-receive-pack", url)
raise NotImplementedError(self.fetch_pack)
@@ -467,6 +487,9 @@ elif parsed.scheme == 'git+ssh':
return SSHGitClient(parsed.hostname, port=parsed.port,
username=parsed.username), parsed.path
+ elif parsed.scheme == 'http':
+ return HttpGitClient(parsed.hostname, port=parsed.port,
+ username=parsed.username), parsed.path
if parsed.scheme and not parsed.netloc:
# SSH with no user@, zero or one leading slash.
|
@@ -30,6 +30,7 @@ import tempfile
import threading
import urllib
+import urlparse
from dulwich import (
client,
@@ -296,6 +297,7 @@ env['SERVER_PROTOCOL'] = self.protocol_version
env['SERVER_PORT'] = str(self.server.server_port)
env['GIT_PROJECT_ROOT'] = self.server.root_path
+ env["GIT_HTTP_EXPORT_ALL"] = "1"
env['REQUEST_METHOD'] = self.command
uqrest = urllib.unquote(rest)
env['PATH_INFO'] = uqrest
@@ -369,7 +371,7 @@ while select.select([self.rfile._sock], [], [], 0)[0]:
if not self.rfile._sock.recv(1):
break
- args = ['http-backend']
+ args = ['-c', 'http.uploadpack=true', '-c', 'http.receivepack=true', 'http-backend']
if '=' not in decoded_query:
args.append(decoded_query)
stdout = run_git_or_fail(args, input=data, env=env, stderr=subprocess.PIPE)
@@ -405,7 +407,7 @@ def setUp(self):
CompatTestCase.setUp(self)
DulwichClientTestBase.setUp(self)
- self._httpd = HTTPGitServer(("localhost", 8080), self.gitroot)
+ self._httpd = HTTPGitServer(("localhost", 0), self.gitroot)
self.addCleanup(self._httpd.shutdown)
threading.Thread(target=self._httpd.serve_forever).start()
@@ -414,7 +416,8 @@ CompatTestCase.tearDown(self)
def _client(self):
- return client.HttpGitClient(self._httpd.get_url())
+ ret, self._path = client.HttpGitClient.from_url(self._httpd.get_url())
+ return ret
def _build_path(self, path):
- return path
+ return urlparse.urljoin(self._path.strip("/"), path.strip("/"))
|
Loading...