remote.txt 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. .. _tutorial-remote:
  2. Most of the tests in this file require a Dulwich server, so let's start one:
  3. >>> from dulwich.repo import Repo
  4. >>> from dulwich.server import DictBackend, TCPGitServer
  5. >>> import threading
  6. >>> repo = Repo.init("remote", mkdir=True)
  7. >>> cid = repo.do_commit(b"message", committer=b"Jelmer <jelmer@samba.org>")
  8. >>> backend = DictBackend({b'/': repo})
  9. >>> dul_server = TCPGitServer(backend, b'localhost', 0)
  10. >>> server_thread = threading.Thread(target=dul_server.serve)
  11. >>> server_thread.start()
  12. >>> server_address, server_port=dul_server.socket.getsockname()
  13. Remote repositories
  14. ===================
  15. The interface for remote Git repositories is different from that
  16. for local repositories.
  17. The Git smart server protocol provides three basic operations:
  18. * upload-pack - provides a pack with objects requested by the client
  19. * receive-pack - imports a pack with objects provided by the client
  20. * upload-archive - provides a tarball with the contents of a specific revision
  21. The smart server protocol can be accessed over either plain TCP (git://),
  22. SSH (git+ssh://) or tunneled over HTTP (http://).
  23. Dulwich provides support for accessing remote repositories in
  24. ``dulwich.client``. To create a new client, you can construct
  25. one manually::
  26. >>> from dulwich.client import TCPGitClient
  27. >>> client = TCPGitClient(server_address, server_port)
  28. Retrieving raw pack files
  29. -------------------------
  30. The client object can then be used to retrieve a pack. The ``fetch_pack``
  31. method takes a ``determine_wants`` callback argument, which allows the
  32. client to determine which objects it wants to end up with::
  33. >>> def determine_wants(refs, depth=None):
  34. ... # retrieve all objects
  35. ... return refs.values()
  36. Note that the ``depth`` keyword argument will contain an optional requested
  37. shallow fetch depth.
  38. Another required object is a "graph walker", which is used to determine
  39. which objects that the client already has should not be sent again
  40. by the server. Here in the tutorial we'll just use a dummy graph walker
  41. which claims that the client doesn't have any objects::
  42. >>> class DummyGraphWalker(object):
  43. ... def ack(self, sha): pass
  44. ... def nak(self): pass
  45. ... def next(self): pass
  46. ... def __next__(self): pass
  47. With the ``determine_wants`` function in place, we can now fetch a pack,
  48. which we will write to a ``BytesIO`` object::
  49. >>> from io import BytesIO
  50. >>> f = BytesIO()
  51. >>> result = client.fetch_pack(b"/", determine_wants,
  52. ... DummyGraphWalker(), pack_data=f.write)
  53. ``f`` will now contain a full pack file::
  54. >>> print(f.getvalue()[:4].decode('ascii'))
  55. PACK
  56. Fetching objects into a local repository
  57. ----------------------------------------
  58. It is also possible to fetch from a remote repository into a local repository,
  59. in which case Dulwich takes care of providing the right graph walker, and
  60. importing the received pack file into the local repository::
  61. >>> from dulwich.repo import Repo
  62. >>> local = Repo.init("local", mkdir=True)
  63. >>> remote_refs = client.fetch(b"/", local)
  64. >>> local.close()
  65. Let's shut down the server now that all tests have been run::
  66. >>> dul_server.shutdown()