|
@@ -0,0 +1,83 @@
|
|
|
+.. _tutorial-remote:
|
|
|
+
|
|
|
+Most of the tests in this file require a Dulwich server, so let's start one:
|
|
|
+
|
|
|
+ >>> from dulwich.repo import Repo
|
|
|
+ >>> from dulwich.server import DictBackend, TCPGitServer
|
|
|
+ >>> import threading
|
|
|
+ >>> repo = Repo.init("remote", mkdir=True)
|
|
|
+ >>> cid = repo.do_commit("message")
|
|
|
+ >>> backend = DictBackend({'/': repo})
|
|
|
+ >>> dul_server = TCPGitServer(backend, 'localhost', 0)
|
|
|
+ >>> threading.Thread(target=dul_server.serve).start()
|
|
|
+ >>> server_address, server_port = dul_server.socket.getsockname()
|
|
|
+
|
|
|
+Remote repositories
|
|
|
+===================
|
|
|
+
|
|
|
+The interface for remote Git repositories is different from that
|
|
|
+for local repositories.
|
|
|
+
|
|
|
+The Git smart server protocol provides three basic operations:
|
|
|
+
|
|
|
+ * upload-pack - provides a pack with objects requested by the client
|
|
|
+ * receive-pack - imports a pack with objects provided by the client
|
|
|
+ * upload-archive - provides a tarball with the contents of a specific revision
|
|
|
+
|
|
|
+The smart server protocol can be accessed over either plain TCP (git://),
|
|
|
+SSH (git+ssh://) or tunneled over HTTP (http://).
|
|
|
+
|
|
|
+Dulwich provides support for accessing remote repositories in
|
|
|
+``dulwich.client``. To create a new client, you can either construct
|
|
|
+one manually::
|
|
|
+
|
|
|
+ >>> from dulwich.client import TCPGitClient
|
|
|
+ >>> client = TCPGitClient(server_address, server_port)
|
|
|
+
|
|
|
+Retrieving raw pack files
|
|
|
+-------------------------
|
|
|
+
|
|
|
+The client object can then be used to retrieve a pack. The ``fetch_pack``
|
|
|
+method takes a ``determine_wants`` callback argument, which allows the
|
|
|
+client to determine which objects it wants to end up with::
|
|
|
+
|
|
|
+ >>> def determine_wants(refs):
|
|
|
+ ... # retrieve all objects
|
|
|
+ ... return refs.values()
|
|
|
+
|
|
|
+Another required object is a "graph walker", which is used to determine
|
|
|
+which objects that the client already has should not be sent again
|
|
|
+by the server. Here in the tutorial we'll just use a dummy graph walker
|
|
|
+which claims that the client doesn't have any objects::
|
|
|
+
|
|
|
+ >>> class DummyGraphWalker(object):
|
|
|
+ ... def ack(self, sha): pass
|
|
|
+ ... def next(self): pass
|
|
|
+
|
|
|
+With the determine_wants function in place, we can now fetch a pack,
|
|
|
+which we will write to a ``StringIO`` object::
|
|
|
+
|
|
|
+ >>> from cStringIO import StringIO
|
|
|
+ >>> f = StringIO()
|
|
|
+ >>> remote_refs = client.fetch_pack("/", determine_wants,
|
|
|
+ ... DummyGraphWalker(), pack_data=f.write)
|
|
|
+
|
|
|
+``f`` will now contain a full pack file::
|
|
|
+
|
|
|
+ >>> f.getvalue()[:4]
|
|
|
+ 'PACK'
|
|
|
+
|
|
|
+Fetching objects into a local repository
|
|
|
+----------------------------------------
|
|
|
+
|
|
|
+It also possible to fetch from a remote repository into a local repository,
|
|
|
+in which case dulwich takes care of providing the right graph walker, and
|
|
|
+importing the received pack file into the local repository::
|
|
|
+
|
|
|
+ >>> from dulwich.repo import Repo
|
|
|
+ >>> local = Repo.init("local", mkdir=True)
|
|
|
+ >>> remote_refs = client.fetch("/", local)
|
|
|
+
|
|
|
+Let's show down the server now that all tests have been run::
|
|
|
+
|
|
|
+ >>> dul_server.shutdown()
|