Forráskód Böngészése

merge support for generating fastexport streams.

Jelmer Vernooij 15 éve
szülő
commit
5ae446fa57
4 módosított fájl, 164 hozzáadás és 0 törlés
  1. 3 0
      NEWS
  2. 82 0
      dulwich/fastexport.py
  3. 1 0
      dulwich/tests/__init__.py
  4. 78 0
      dulwich/tests/test_fastexport.py

+ 3 - 0
NEWS

@@ -20,6 +20,9 @@
 
   * Add include-tag capability to server. (Dave Borowitz)
 
+  * New dulwich.fastexport module that can generate fastexport 
+    streams. (Jelmer Vernooij)
+
  TESTS
 
   * Add framework for testing compatibility with C Git. (Dave Borowitz)

+ 82 - 0
dulwich/fastexport.py

@@ -0,0 +1,82 @@
+# __init__.py -- Fast export/import functionality
+# Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License or (at your option) any later version of 
+# the License.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.
+
+
+"""Fast export/import functionality."""
+
+from dulwich.objects import (
+    Tree,
+    format_timezone,
+    )
+
+import stat
+
+class FastExporter(object):
+    """Generate a fast-export output stream for Git objects."""
+
+    def __init__(self, outf, store):
+        self.outf = outf
+        self.store = store
+        self.markers = {}
+        self._marker_idx = 0
+
+    def _allocate_marker(self):
+        self._marker_idx+=1
+        return self._marker_idx
+
+    def _dump_blob(self, blob, marker):
+        self.outf.write("blob\nmark :%s\n" % marker)
+        self.outf.write("data %s\n" % blob.raw_length())
+        for chunk in blob.as_raw_chunks():
+            self.outf.write(chunk)
+        self.outf.write("\n")
+
+    def export_blob(self, blob):
+        i = self._allocate_marker()
+        self.markers[i] = blob.id
+        self._dump_blob(blob, i)
+        return i
+
+    def _dump_commit(self, commit, marker, ref, file_changes):
+        self.outf.write("commit %s\n" % ref)
+        self.outf.write("mark :%s\n" % marker)
+        self.outf.write("author %s %s %s\n" % (commit.author,
+            commit.author_time, format_timezone(commit.author_timezone)))
+        self.outf.write("committer %s %s %s\n" % (commit.committer,
+            commit.commit_time, format_timezone(commit.commit_timezone)))
+        self.outf.write("data %s\n" % len(commit.message))
+        self.outf.write(commit.message)
+        self.outf.write("\n")
+        self.outf.write('\n'.join(file_changes))
+        self.outf.write("\n\n")
+
+    def export_commit(self, commit, ref, base_tree=None):
+        file_changes = []
+        for (old_path, new_path), (old_mode, new_mode), (old_hexsha, new_hexsha) in \
+                self.store.tree_changes(base_tree, commit.tree):
+            if new_path is None:
+                file_changes.append("D %s" % old_path)
+                continue
+            if not stat.S_ISDIR(new_mode):
+                marker = self.export_blob(self.store[new_hexsha])
+            file_changes.append("M %o :%s %s" % (new_mode, marker, new_path))
+
+        i = self._allocate_marker()
+        self._dump_commit(commit, i, ref, file_changes)
+        return i

+ 1 - 0
dulwich/tests/__init__.py

@@ -29,6 +29,7 @@ from nose import SkipTest as TestSkipped
 def test_suite():
     names = [
         'client',
+        'fastexport',
         'file',
         'index',
         'lru_cache',

+ 78 - 0
dulwich/tests/test_fastexport.py

@@ -0,0 +1,78 @@
+# test_fastexport.py -- Fast export/import functionality
+# Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License or (at your option) any later version of 
+# the License.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.
+
+from cStringIO import StringIO
+import stat
+from unittest import TestCase
+
+from dulwich.fastexport import (
+    FastExporter,
+    )
+from dulwich.object_store import (
+    MemoryObjectStore,
+    )
+from dulwich.objects import (
+    Blob,
+    Commit,
+    Tree,
+    )
+
+
+class FastExporterTests(TestCase):
+
+    def setUp(self):
+        super(FastExporterTests, self).setUp()
+        self.store = MemoryObjectStore()
+        self.stream = StringIO()
+        self.fastexporter = FastExporter(self.stream, self.store)
+
+    def test_export_blob(self):
+        b = Blob()
+        b.data = "fooBAR"
+        self.assertEquals(1, self.fastexporter.export_blob(b))
+        self.assertEquals('blob\nmark :1\ndata 6\nfooBAR\n',
+            self.stream.getvalue())
+
+    def test_export_commit(self):
+        b = Blob()
+        b.data = "FOO"
+        t = Tree()
+        t.add(stat.S_IFREG | 0644, "foo", b.id)
+        c = Commit()
+        c.committer = c.author = "Jelmer <jelmer@host>"
+        c.author_time = c.commit_time = 1271345553.47
+        c.author_timezone = c.commit_timezone = 0
+        c.message = "msg"
+        c.tree = t.id
+        self.store.add_objects([(b, None), (t, None), (c, None)])
+        self.assertEquals(2,
+                self.fastexporter.export_commit(c, "refs/heads/master"))
+        self.assertEquals("""blob
+mark :1
+data 3
+FOO
+commit refs/heads/master
+mark :2
+author Jelmer <jelmer@host> 1271345553.47 +0000
+committer Jelmer <jelmer@host> 1271345553.47 +0000
+data 3
+msg
+M 100644 :1 foo
+
+""", self.stream.getvalue())