Browse Source

Add clone to porcelain.

Jelmer Vernooij 11 years ago
parent
commit
a9f9b6261e
3 changed files with 46 additions and 13 deletions
  1. 7 12
      bin/dulwich
  2. 25 0
      dulwich/porcelain.py
  3. 14 1
      dulwich/tests/test_porcelain.py

+ 7 - 12
bin/dulwich

@@ -35,6 +35,7 @@ from dulwich.errors import ApplyDeltaError
 from dulwich.index import Index
 from dulwich.porcelain import (
     archive,
+    clone,
     commit,
     init,
     update_server_info,
@@ -169,26 +170,20 @@ def cmd_init(args):
 
 
 def cmd_clone(args):
-    opts, args = getopt(args, "", [])
+    opts, args = getopt(args, "", ["bare"])
     opts = dict(opts)
 
     if args == []:
         print "usage: dulwich clone host:path [PATH]"
         sys.exit(1)
-    client, host_path = get_transport_and_path(args.pop(0))
 
+    source = args.pop(0)
     if len(args) > 0:
-        path = args.pop(0)
+        target = args.pop(0)
     else:
-        path = host_path.split("/")[-1]
-
-    if not os.path.exists(path):
-        os.mkdir(path)
-    r = Repo.init(path)
-    remote_refs = client.fetch(host_path, r,
-        determine_wants=r.object_store.determine_wants_all,
-        progress=sys.stdout.write)
-    r["HEAD"] = remote_refs["HEAD"]
+        target = None
+
+    clone(source, target, bare=("--bare" in opts))
 
 
 def cmd_commit(args):

+ 25 - 0
dulwich/porcelain.py

@@ -83,3 +83,28 @@ def init(path=".", bare=False):
         Repo.init_bare(path)
     else:
         Repo.init(path)
+
+
+def clone(source, target=None, bare=False, outstream=sys.stdout):
+    """Clone a local or remote git repository.
+
+    :param source: Path or URL for source repository
+    :param target: Path to target repository (optional)
+    :param bare: Whether or not to create a bare repository
+    :param outstream: Optional stream to write progress to
+    """
+    client, host_path = get_transport_and_path(source)
+
+    if target is None:
+        target = host_path.split("/")[-1]
+
+    if not os.path.exists(target):
+        os.mkdir(target)
+    if bare:
+        r = Repo.init_bare(target)
+    else:
+        r = Repo.init(target)
+    remote_refs = client.fetch(host_path, r,
+        determine_wants=r.object_store.determine_wants_all,
+        progress=outstream.write)
+    r["HEAD"] = remote_refs["HEAD"]

+ 14 - 1
dulwich/tests/test_porcelain.py

@@ -26,6 +26,7 @@ import tempfile
 
 from dulwich.porcelain import (
     archive,
+    clone,
     commit,
     init,
     update_server_info,
@@ -84,7 +85,19 @@ class CommitTests(PorcelainTestCase):
         commit(self.repo.path, message="Some message")
 
 
-class CommitTests(TestCase):
+class CloneTests(PorcelainTestCase):
+
+    def test_simple_local(self):
+        c1, c2, c3 = build_commit_graph(self.repo.object_store, [[1], [2, 1], [3, 1, 2]])
+        self.repo.refs["refs/heads/master"] = c3.id
+        target_path = tempfile.mkdtemp()
+        outstream = StringIO()
+        self.addCleanup(shutil.rmtree, target_path)
+        clone(self.repo.path, target_path, outstream=outstream)
+        self.assertEquals(Repo(target_path).head(), c3.id)
+
+
+class InitTests(TestCase):
 
     def test_non_bare(self):
         repo_dir = tempfile.mkdtemp()