← Back to team overview

dulwich-users team mailing list archive

[PATCH] Allow accessing invalidly named refs, but don't allow setting them.

 

We discussed invalidly named refs earlier, and allowing to access them
but raising exceptions when the user attempts to set them.

Does this seem like a reasonable patch?

Cheers,

Jelmer
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: jelmer@xxxxxxxxx-20110117060040-kzpfwnq4g3e6tvn1
# target_branch: file:///home/jelmer/src/dulwich/speedup/
# testament_sha1: f68f3ce566d45f14dfa8ae6a69462a003c9d89d7
# timestamp: 2011-01-17 07:01:04 +0100
# base_revision_id: git-v1:0605f08122d11ab14e2c1634807615f7011f23c1
# 
# Begin patch
=== modified file '.bzrignore'
--- .bzrignore	2009-05-13 14:12:41 +0000
+++ .bzrignore	2010-11-26 15:32:32 +0000
@@ -4,3 +4,5 @@
 dist
 apidocs
 *,cover
+.testrepository
+docs/tutorial/index.html

=== added file '.testr.conf'
--- .testr.conf	1970-01-01 00:00:00 +0000
+++ .testr.conf	2010-12-19 19:39:07 +0000
@@ -0,0 +1,4 @@
+[DEFAULT]
+test_command=PYTHONPATH=. python -m subunit.run $IDOPTION $LISTOPT dulwich.tests.test_suite
+test_id_option=--load-list $IDFILE
+test_list_option=--list

=== modified file 'AUTHORS'
--- AUTHORS	2009-03-05 15:26:05 +0000
+++ AUTHORS	2010-11-26 15:32:32 +0000
@@ -1,3 +1,8 @@
+Jelmer Vernooij <jelmer@xxxxxxxxx>
 James Westby <jw+debian@xxxxxxxxxxxxxxx>
 John Carr <john.carr@xxxxxxxxxxxxxx>
-Jelmer Vernooij <jelmer@xxxxxxxxx>
+Dave Borowitz <dborowitz@xxxxxxxxxx>
+
+Hervé Cauwelier <herve@xxxxxxxxxx> wrote the original tutorial.
+
+See the revision history for a full list of contributors.

=== modified file 'HACKING'
--- HACKING	2009-08-09 11:27:32 +0000
+++ HACKING	2011-01-05 11:35:31 +0000
@@ -1,5 +1,11 @@
-Please follow PEP8 with regard to coding style.
-
-All functionality should be available in pure Python. Optional C implementations
-may be written for performance reasons, but should never replace the Python 
-implementation. The C implementations should follow the kernel/git coding style.
+Where possible, please follow PEP8 with regard to coding style.
+
+Furthermore, triple-quotes should always be """, single quotes are ' unless using "
+would result in less escaping within the string.
+
+All functionality should be available in pure Python. Optional C
+implementations may be written for performance reasons, but should never
+replace the Python implementation. The C implementations should follow the
+kernel/git coding style.
+
+Where possible please include updates to NEWS along with your improvements.

=== modified file 'Makefile'
--- Makefile	2009-06-16 14:56:42 +0000
+++ Makefile	2011-01-05 11:30:29 +0000
@@ -1,9 +1,14 @@
 PYTHON = python
 SETUP = $(PYTHON) setup.py
 PYDOCTOR ?= pydoctor
-TESTRUNNER = $(shell which nosetests)
+ifeq ($(shell $(PYTHON) -c "import sys; print sys.version_info >= (2, 7)"),True)
+TESTRUNNER ?= unittest
+else
+TESTRUNNER ?= unittest2.__main__
+endif
+RUNTEST = PYTHONPATH=.:$(PYTHONPATH) $(PYTHON) -m $(TESTRUNNER)
 
-all: build 
+all: build
 
 doc:: pydoctor
 
@@ -18,17 +23,14 @@
 	$(SETUP) install
 
 check:: build
-	PYTHONPATH=. $(PYTHON) $(TESTRUNNER) dulwich
+	$(RUNTEST) dulwich.tests.test_suite
+
+check-nocompat:: build
+	$(RUNTEST) dulwich.tests.nocompat_test_suite
 
 check-noextensions:: clean
-	PYTHONPATH=. $(PYTHON) $(TESTRUNNER) dulwich
+	$(RUNTEST) dulwich.tests.test_suite
 
 clean::
 	$(SETUP) clean --all
 	rm -f dulwich/*.so
-
-coverage:: build
-	PYTHONPATH=. $(PYTHON) $(TESTRUNNER) --cover-package=dulwich --with-coverage --cover-erase --cover-inclusive dulwich
-
-coverage-annotate: coverage
-	python-coverage -a -o /usr

=== modified file 'NEWS'
--- NEWS	2009-10-09 23:28:45 +0000
+++ NEWS	2010-12-26 02:15:15 +0000
@@ -1,14 +1,323 @@
-0.4.1	UNRELEASED
-
- FEATURES
-
-  * Add ObjectStore.iter_tree_contents()
-
-  * Add Index.changes_from_tree()
-
-  * Add ObjectStore.tree_changes()
+0.7.0	UNRELEASED
+
+ FEATURES
+
+  * New `dulwich.diff_tree` module for simple content-based rename detection.
+    (Dave Borowitz)
+
+  * Add Tree.items(). (Jelmer Vernooij)
+
+  * Add eof() and unread_pkt_line() methods to Protocol. (Dave Borowitz)
+
+  * Add write_tree_diff(). (Jelmer Vernooij)
+
+  * Add `serve_command` function for git server commands as executables.
+    (Jelmer Vernooij)
+
+  * dulwich.client.get_transport_and_path now supports rsync-style repository URLs.
+    (Dave Borowitz, #568493)
+
+ BUG FIXES
+
+  * Correct short-circuiting operation for no-op fetches in the server.
+    (Dave Borowitz)
+
+  * Support parsing git mbox patches without a version tail, as generated by
+    Mercurial.  (Jelmer Vernooij)
+
+  * Fix dul-receive-pack and dul-upload-pack. (Jelmer Vernooij)
+
+  * Zero-padded file modes in Tree objects no longer trigger an exception but
+    the check code warns about them. (Augie Fackler, #581064)
+
+  * Repo.init() now honors the mkdir flag. (#671159)
+
+  * The ref format is now checked when setting a ref rather than when reading it back.
+    (Dave Borowitz, #653527)
+
+  * Make sure pack files are closed correctly. (Tay Ray Chuan)
+
+ DOCUMENTATION
+
+  * Run the tutorial inside the test suite. (Jelmer Vernooij)
+
+  * Reorganized and updated the tutorial. (Jelmer Vernooij, Dave Borowitz, #610550,
+     #610540)
+
+
+0.6.2	2010-10-16
+
+ BUG FIXES
+
+  * HTTP server correctly handles empty CONTENT_LENGTH. (Dave Borowitz)
+
+  * Don't error when creating GitFiles with the default mode. (Dave Borowitz)
+
+  * ThinPackData.from_file now works with resolve_ext_ref callback.
+    (Dave Borowitz)
+
+  * Provide strnlen() on mingw32 which doesn't have it. (Hans Kolek)
+
+  * Set bare=true in the configuratin for bare repositories. (Dirk Neumann)
+
+ FEATURES
+
+  * Use slots for core objects to save up on memory. (Jelmer Vernooij)
+
+  * Web server supports streaming progress/pack output. (Dave Borowitz)
+
+  * New public function dulwich.pack.write_pack_header. (Dave Borowitz)
+
+  * Distinguish between missing files and read errors in HTTP server.
+    (Dave Borowitz)
+
+  * Initial work on support for fastimport using python-fastimport.
+    (Jelmer Vernooij)
+
+  * New dulwich.pack.MemoryPackIndex class. (Jelmer Vernooij)
+
+  * Delegate SHA peeling to the object store.  (Dave Borowitz)
+
+ TESTS
+
+  * Use GitFile when modifying packed-refs in tests. (Dave Borowitz)
+
+  * New tests in test_web with better coverage and fewer ad-hoc mocks.
+    (Dave Borowitz)
+
+  * Standardize quote delimiters in test_protocol. (Dave Borowitz)
+
+  * Fix use when testtools is installed. (Jelmer Vernooij)
+
+  * Add trivial test for write_pack_header. (Jelmer Vernooij)
+
+  * Refactor some of dulwich.tests.compat.server_utils. (Dave Borowitz)
+
+  * Allow overwriting id property of objects in test utils. (Dave Borowitz)
+
+  * Use real in-memory objects rather than stubs for server tests.
+    (Dave Borowitz)
+
+  * Clean up MissingObjectFinder. (Dave Borowitz)
+
+ API CHANGES
+
+  * ObjectStore.iter_tree_contents now walks contents in depth-first, sorted
+    order. (Dave Borowitz)
+
+  * ObjectStore.iter_tree_contents can optionally yield tree objects as well.
+    (Dave Borowitz).
+
+  * Add side-band-64k support to ReceivePackHandler. (Dave Borowitz)
+
+  * Change server capabilities methods to classmethods. (Dave Borowitz)
+
+  * Tweak server handler injection. (Dave Borowitz)
+
+  * PackIndex1 and PackIndex2 now subclass FilePackIndex, which is 
+    itself a subclass of PackIndex. (Jelmer Vernooij)
+
+ DOCUMENTATION
+
+  * Add docstrings for various functions in dulwich.objects. (Jelmer Vernooij)
+
+  * Clean up docstrings in dulwich.protocol. (Dave Borowitz)
+
+  * Explicitly specify allowed protocol commands to
+    ProtocolGraphWalker.read_proto_line.  (Dave Borowitz)
+
+  * Add utility functions to DictRefsContainer. (Dave Borowitz)
+
+
+0.6.1	2010-07-22
+
+ BUG FIXES
+
+  * Fix memory leak in C implementation of sorted_tree_items. (Dave Borowitz)
+
+  * Use correct path separators for named repo files. (Dave Borowitz)
+
+  * python > 2.7 and testtools-based test runners will now also pick up skipped
+    tests correctly. (Jelmer Vernooij)
+
+ FEATURES
+
+  * Move named file initilization to BaseRepo. (Dave Borowitz)
+
+  * Add logging utilities and git/HTTP server logging. (Dave Borowitz)
+
+  * The GitClient interface has been cleaned up and instances are now reusable.
+    (Augie Fackler)
+
+  * Allow overriding paths to executables in GitSSHClient. 
+    (Ross Light, Jelmer Vernooij, #585204)
+
+  * Add PackBasedObjectStore.pack_loose_objects(). (Jelmer Vernooij)
+
+ TESTS
+
+  * Add tests for sorted_tree_items and C implementation. (Dave Borowitz)
+
+  * Add a MemoryRepo that stores everything in memory. (Dave Borowitz)
+
+  * Quiet logging output from web tests. (Dave Borowitz)
+
+  * More flexible version checking for compat tests. (Dave Borowitz)
+
+  * Compat tests for servers with and without side-band-64k. (Dave Borowitz)
+
+ CLEANUP
+
+  * Clean up file headers. (Dave Borowitz)
+
+ TESTS
+
+  * Use GitFile when modifying packed-refs in tests. (Dave Borowitz)
+
+ API CHANGES
+
+  * dulwich.pack.write_pack_index_v{1,2} now take a file-like object
+    rather than a filename. (Jelmer Vernooij)
+
+  * Make dul-daemon/dul-web trivial wrappers around server functionality.
+    (Dave Borowitz)
+
+  * Move reference WSGI handler to web.py. (Dave Borowitz)
+
+  * Factor out _report_status in ReceivePackHandler. (Dave Borowitz)
+
+  * Factor out a function to convert a line to a pkt-line. (Dave Borowitz)
+
+
+0.6.0	2010-05-22
+
+note: This list is most likely incomplete for 0.6.0.
+
+ BUG FIXES
+ 
+  * Fix ReceivePackHandler to disallow removing refs without delete-refs.
+    (Dave Borowitz)
+
+  * Deal with capabilities required by the client, even if they 
+    can not be disabled in the server. (Dave Borowitz)
+
+  * Fix trailing newlines in generated patch files.
+    (Jelmer Vernooij)
+
+  * Implement RefsContainer.__contains__. (Jelmer Vernooij)
+
+  * Cope with \r in ref files on Windows. (
+    http://github.com/jelmer/dulwich/issues/#issue/13, Jelmer Vernooij)
+
+  * Fix GitFile breakage on Windows. (Anatoly Techtonik, #557585)
+
+  * Support packed ref deletion with no peeled refs. (Augie Fackler)
+
+  * Fix send pack when there is nothing to fetch. (Augie Fackler)
+
+  * Fix fetch if no progress function is specified. (Augie Fackler)
+
+  * Allow double-staging of files that are deleted in the index. 
+    (Dave Borowitz)
+
+  * Fix RefsContainer.add_if_new to support dangling symrefs.
+    (Dave Borowitz)
+
+  * Non-existant index files in non-bare repositories are now treated as 
+    empty. (Dave Borowitz)
+
+  * Always update ShaFile.id when the contents of the object get changed. 
+    (Jelmer Vernooij)
+
+  * Various Python2.4-compatibility fixes. (Dave Borowitz)
+
+  * Fix thin pack handling. (Dave Borowitz)
+ 
+ FEATURES
+
+  * Add include-tag capability to server. (Dave Borowitz)
+
+  * New dulwich.fastexport module that can generate fastexport 
+    streams. (Jelmer Vernooij)
+
+  * Implemented BaseRepo.__contains__. (Jelmer Vernooij)
+
+  * Add __setitem__ to DictRefsContainer. (Dave Borowitz)
+
+  * Overall improvements checking Git objects. (Dave Borowitz)
+
+  * Packs are now verified while they are received. (Dave Borowitz)
+
+ TESTS
+
+  * Add framework for testing compatibility with C Git. (Dave Borowitz)
+
+  * Add various tests for the use of non-bare repositories. (Dave Borowitz)
+
+  * Cope with diffstat not being available on all platforms. 
+    (Tay Ray Chuan, Jelmer Vernooij)
+
+  * Add make_object and make_commit convenience functions to test utils.
+    (Dave Borowitz)
+
+ API BREAKAGES
+
+  * The 'committer' and 'message' arguments to Repo.do_commit() have 
+    been swapped. 'committer' is now optional. (Jelmer Vernooij)
+
+  * Repo.get_blob, Repo.commit, Repo.tag and Repo.tree are now deprecated.
+    (Jelmer Vernooij)
+
+  * RefsContainer.set_ref() was renamed to RefsContainer.set_symbolic_ref(),
+    for clarity. (Jelmer Vernooij)
+
+ API CHANGES
+
+  * The primary serialization APIs in dulwich.objects now work 
+    with chunks of strings rather than with full-text strings. 
+    (Jelmer Vernooij)
+
+0.5.02010-03-03
+
+ BUG FIXES
+
+  * Support custom fields in commits (readonly). (Jelmer Vernooij)
+
+  * Improved ref handling. (Dave Borowitz)
+
+  * Rework server protocol to be smarter and interoperate with cgit client.
+    (Dave Borowitz)
+
+  * Add a GitFile class that uses the same locking protocol for writes as 
+    cgit. (Dave Borowitz)
+
+  * Cope with forward slashes correctly in the index on Windows.
+    (Jelmer Vernooij, #526793)
+
+ FEATURES
+
+  * --pure option to setup.py to allow building/installing without the C 
+    extensions. (Hal Wine, Anatoly Techtonik, Jelmer Vernooij, #434326)
+
+  * Implement Repo.get_config(). (Jelmer Vernooij, Augie Fackler)
+
+  * HTTP dumb and smart server. (Dave Borowitz)
+
+  * Add abstract baseclass for Repo that does not require file system 
+    operations. (Dave Borowitz)
+
+0.4.1	2010-01-03
+
+ FEATURES
+
+  * Add ObjectStore.iter_tree_contents(). (Jelmer Vernooij)
+
+  * Add Index.changes_from_tree(). (Jelmer Vernooij)
+
+  * Add ObjectStore.tree_changes(). (Jelmer Vernooij)
 
   * Add functionality for writing patches in dulwich.patch.
+    (Jelmer Vernooij)
 
 0.4.0	2009-10-07
 
@@ -69,7 +378,7 @@
 
   * Removed Repo.set_ref, Repo.remove_ref, Repo.tags, Repo.get_refs and 
     Repo.heads in favor of Repo.refs, a dictionary-like object for accessing
-	refs.
+    refs.
 
  BUG FIXES
 

=== modified file 'README'
--- README	2009-09-13 15:01:07 +0000
+++ README	2010-04-13 23:22:43 +0000
@@ -21,3 +21,7 @@
 in the particular Monty Python sketch. It is based on the Python-Git module 
 that James Westby <jw+debian@xxxxxxxxxxxxxxx> released in 2007 and now 
 maintained by Jelmer Vernooij and John Carr.
+
+Please file bugs in the Dulwich project on Launchpad: 
+
+https://bugs.launchpad.net/dulwich/+filebug

=== modified file 'bin/dul-daemon'
--- bin/dul-daemon	2008-12-24 23:51:08 +0000
+++ bin/dul-daemon	2010-07-21 11:33:38 +0000
@@ -1,30 +1,23 @@
 #!/usr/bin/python
-# dul-daemon - Simple git-daemon a like
+# dul-daemon - Simple git-daemon-like server
 # Copyright (C) 2008 John Carr <john.carr@xxxxxxxxxxxxxx>
-# 
+#
 # 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) a 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.
 
-import sys
-from dulwich.server import GitBackend, TCPGitServer
-
-if __name__ == "__main__":
-    gitdir = None
-    if len(sys.argv) > 1:
-        gitdir = sys.argv[1]
-
-    backend = GitBackend(gitdir)
-    server = TCPGitServer(backend, 'localhost')
-    server.serve_forever()
+from dulwich.server import main
+
+if __name__ == '__main__':
+    main()

=== modified file 'bin/dul-receive-pack'
--- bin/dul-receive-pack	2008-12-24 20:43:49 +0000
+++ bin/dul-receive-pack	2010-12-25 23:09:45 +0000
@@ -1,34 +1,28 @@
 #!/usr/bin/python
 # dul-receive-pack - git-receive-pack in python
 # Copyright (C) 2008 John Carr <john.carr@xxxxxxxxxxxxxx>
-# 
+#
 # 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) a 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 dulwich.server import serve_command, ReceivePackHandler
+import os
 import sys
-from dulwich.server import GitBackend, ReceivePackHandler
-
-def send_fn(data):
-    sys.stdout.write(data)
-    sys.stdout.flush()
-
-if __name__ == "__main__":
-    gitdir = None
-    if len(sys.argv) > 1:
-        gitdir = sys.argv[1]
-
-    backend = GitBackend(gitdir)
-    handler = ReceivePackHandler(backend, sys.stdin.read, send_fn)
-    handler.handle()
+
+if len(sys.argv) < 2:
+    print >>sys.stderr, "usage: %s <git-dir>" % os.path.basename(sys.argv[0])
+    sys.exit(1)
+
+sys.exit(serve_command(ReceivePackHandler))

=== modified file 'bin/dul-upload-pack'
--- bin/dul-upload-pack	2008-12-24 20:43:49 +0000
+++ bin/dul-upload-pack	2010-12-25 23:09:45 +0000
@@ -1,34 +1,28 @@
 #!/usr/bin/python
 # dul-upload-pack - git-upload-pack in python
 # Copyright (C) 2008 John Carr <john.carr@xxxxxxxxxxxxxx>
-# 
+#
 # 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) a 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 dulwich.server import serve_command, UploadPackHandler
+import os
 import sys
-from dulwich.server import GitBackend, UploadPackHandler
-
-def send_fn(data):
-    sys.stdout.write(data)
-    sys.stdout.flush()
-
-if __name__ == "__main__":
-    gitdir = None
-    if len(sys.argv) > 1:
-        gitdir = sys.argv[1]
-
-    backend = GitBackend(gitdir)
-    handler = UploadPackHandler(backend, sys.stdin.read, send_fn)
-    handler.handle()
+
+if len(sys.argv) < 2:
+    print >>sys.stderr, "usage: %s <git-dir>" % os.path.basename(sys.argv[0])
+    sys.exit(1)
+
+sys.exit(serve_command(UploadPackHandler))

=== added file 'bin/dul-web'
--- bin/dul-web	1970-01-01 00:00:00 +0000
+++ bin/dul-web	2010-07-21 11:34:59 +0000
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+# dul-web - HTTP-based git server
+# Copyright (C) 2010 Google, Inc. <dborowitz@xxxxxxxxxx>
+#
+# 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
+# or (at your option) a 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 dulwich.web import main
+
+if __name__ == '__main__':
+    main()

=== modified file 'bin/dulwich'
--- bin/dulwich	2009-10-18 17:24:17 +0000
+++ bin/dulwich	2010-05-24 17:21:02 +0000
@@ -1,37 +1,41 @@
 #!/usr/bin/python
-# dul-daemon - Simple git smart server client
+# dulwich - Simple command-line interface to Dulwich
 # Copyright (C) 2008 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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
 # or (at your option) a 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.
 
+"""Simple command-line interface to Dulwich>
+
+This is a very simple command-line wrapper for Dulwich. It is by 
+no means intended to be a full-blown Git command-line interface but just 
+a way to test Dulwich.
+"""
+
+import os
 import sys
 from getopt import getopt
 
-def get_transport_and_path(uri):
-    from dulwich.client import TCPGitClient, SSHGitClient, SubprocessGitClient
-    for handler, transport in (("git://", TCPGitClient), ("git+ssh://", SSHGitClient)):
-        if uri.startswith(handler):
-            host, path = uri[len(handler):].split("/", 1)
-            return transport(host), "/"+path
-    # if its not git or git+ssh, try a local url..
-    return SubprocessGitClient(), uri
+from dulwich.client import get_transport_and_path
+from dulwich.errors import ApplyDeltaError
+from dulwich.index import Index
+from dulwich.pack import Pack, sha_to_hex
+from dulwich.repo import Repo
 
 
 def cmd_fetch_pack(args):
-    from dulwich.repo import Repo
     opts, args = getopt(args, "", ["all"])
     opts = dict(opts)
     client, path = get_transport_and_path(args.pop(0))
@@ -45,9 +49,12 @@
 
 
 def cmd_log(args):
-    from dulwich.repo import Repo
     opts, args = getopt(args, "", [])
-    r = Repo(".")
+    if len(args) > 0:
+        path = args.pop(0)
+    else:
+        path = "."
+    r = Repo(path)
     todo = [r.head()]
     done = set()
     while todo:
@@ -56,7 +63,7 @@
         if sha in done:
             continue
         done.add(sha)
-        commit = r.commit(sha)
+        commit = r[sha]
         print "-" * 50
         print "commit: %s" % sha
         if len(commit.parents) > 1:
@@ -70,11 +77,6 @@
 
 
 def cmd_dump_pack(args):
-    from dulwich.errors import ApplyDeltaError
-    from dulwich.pack import Pack, sha_to_hex
-    import os
-    import sys
-
     opts, args = getopt(args, "", [])
 
     if args == []:
@@ -98,8 +100,6 @@
 
 
 def cmd_dump_index(args):
-    from dulwich.index import Index
-
     opts, args = getopt(args, "", [])
 
     if args == []:
@@ -114,8 +114,6 @@
 
 
 def cmd_init(args):
-    from dulwich.repo import Repo
-    import os
     opts, args = getopt(args, "", ["--bare"])
     opts = dict(opts)
 
@@ -134,16 +132,13 @@
 
 
 def cmd_clone(args):
-    from dulwich.repo import Repo
-    import os
-    import sys
     opts, args = getopt(args, "", [])
     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))
+    client, host_path = get_transport_and_path(args.pop(0))
 
     if len(args) > 0:
         path = args.pop(0)
@@ -152,18 +147,14 @@
 
     if not os.path.exists(path):
         os.mkdir(path)
-    Repo.init(path)
-    r = Repo(path)
-    graphwalker = r.get_graph_walker()
-    f, commit = r.object_store.add_pack()
-    client.fetch_pack(host_path, r.object_store.determine_wants_all, 
-                      graphwalker, f.write, sys.stdout.write)
-    commit()
+    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"]
 
 
 def cmd_commit(args):
-    from dulwich.repo import Repo
-    import os
     opts, args = getopt(args, "", ["message"])
     opts = dict(opts)
     r = Repo(".")
@@ -173,6 +164,7 @@
                           os.getenv("GIT_AUTHOR_EMAIL"))
     r.do_commit(committer=committer, author=author, message=opts["--message"])
 
+
 commands = {
     "commit": cmd_commit,
     "fetch-pack": cmd_fetch_pack,

=== modified file 'docs/tutorial/0-introduction.txt'
--- docs/tutorial/0-introduction.txt	2009-09-16 20:26:03 +0000
+++ docs/tutorial/0-introduction.txt	2010-11-26 15:32:32 +0000
@@ -45,16 +45,16 @@
 The Tree
 --------
 
-A tree is a collection of file information, the state of your working copy at
+A tree is a collection of file information, the state of a single directory at
 a given point in time.
 
 A tree file looks like this::
 
-  tree <content length><NUL><file mode> <filename><NUL><blob sha>...
+  tree <content length><NUL><file mode> <filename><NUL><item sha>...
 
 And repeats for every file in the tree.
 
-Note that for a unknown reason, the SHA-1 digest is in binary form here.
+Note that the SHA-1 digest is in binary form here.
 
 The file mode is like the octal argument you could give to the ``chmod``
 command.  Except it is in extended form to tell regular files from
@@ -88,14 +88,15 @@
 More About Git formats
 ----------------------
 
-These three objects make 90 % of a Git repository. The rest is branch
-information and optimizations.
-
-For instance there is an index of the current state of the working copy.
-There are also pack files to group several small objects in a single indexed
-file.
-
-For a more detailled explanation of object formats and SHA-1 digests, see:
+These three objects make up most of the contents of a Git repository and are
+used for the history. They can either appear as simple files on disk (one file
+per object) or in a ``pack`` file, which is a container for a number of these
+objects.
+
+The is also an index of the current state of the working copy in the
+repository as well as files to track the existing branches and tags.
+
+For a more detailed explanation of object formats and SHA-1 digests, see:
 http://www-cs-students.stanford.edu/~blynn/gitmagic/ch08.html
 
 Just note that recent versions of Git compress object files using zlib.

=== removed file 'docs/tutorial/1-initial-commit.txt'
--- docs/tutorial/1-initial-commit.txt	2009-10-06 13:47:16 +0000
+++ docs/tutorial/1-initial-commit.txt	1970-01-01 00:00:00 +0000
@@ -1,119 +0,0 @@
-The Repository
-==============
-
-After this introduction, let's start directly with code::
-
-  >>> from dulwich.repo import Repo
-
-The access to every object is through the Repo object. You can open an
-existing repository or you can create a new one. There are two types of Git
-repositories:
-
-  Regular Repositories -- They are the ones you create using ``git init`` and
-  you daily use. They contain a ``.git`` folder.
-
-  Bare Repositories -- There is not ".git" folder. The top-level folder
-  contains itself the "branches", "hooks"... folders. These are used for
-  published repositories (mirrors).
-
-Let's create a folder and turn it into a repository, like ``git init`` would::
-
-  >>> from os import mkdir
-  >>> mkdir("myrepo")
-  >>> repo = Repo.init("myrepo")
-  >>> repo
-  <Repo at '/tmp/myrepo/'>
-
-You can already look a the structure of the "myrepo/.git" folder, though it
-is mostly empty for now.
-
-Initial commit
-==============
-
-When you use Git, you generally add or modify content. As our repository is
-empty for now, we'll start by adding a new file::
-
-  >>> from dulwich.objects import Blob
-  >>> blob = Blob.from_string("My file content\n")
-  >>> blob.id
-  'c55063a4d5d37aa1af2b2dad3a70aa34dae54dc6'
-
-Of course you could create a blob from an existing file using ``from_file``
-instead.
-
-As said in the introduction, file content is separed from file name. Let's
-give this content a name::
-
-  >>> from dulwich.objects import Tree
-  >>> tree = Tree()
-  >>> tree.add(0100644, "spam", blob.id)
-
-Note that "0100644" is the octal form for a regular file with common
-permissions. You can hardcode them or you can use the ``stat`` module.
-
-The tree state of our repository still needs to be placed in time. That's the
-job of the commit::
-
-  >>> from dulwich.objects import Commit, parse_timezone
-  >>> from time import time
-  >>> commit = Commit()
-  >>> commit.tree = tree.id
-  >>> author = "Your Name <your.email@xxxxxxxxxxx>"
-  >>> commit.author = commit.committer = author
-  >>> commit.commit_time = commit.author_time = int(time())
-  >>> tz = parse_timezone('-0200')
-  >>> commit.commit_timezone = commit.author_timezone = tz
-  >>> commit.encoding = "UTF-8"
-  >>> commit.message = "Initial commit"
-
-Note that the initial commit has no parents.
-
-At this point, the repository is still empty because all operations happen in
-memory. Let's "commit" it.
-
-  >>> object_store = repo.object_store
-  >>> object_store.add_object(blob)
-
-Now the ".git/objects" folder contains a first SHA-1 file. Let's continue
-saving the changes::
-
-  >>> object_store.add_object(tree)
-  >>> object_store.add_object(commit)
-
-Now the physical repository contains three objects but still has no branch.
-Let's create the master branch like Git would::
-
-  >>> repo.refs['refs/heads/master'] = commit.id
-
-The master branch now has a commit where to start, but Git itself would not
-known what is the current branch. That's another reference::
-
-  >>> repo.refs['HEAD'] = 'ref: refs/heads/master'
-
-Now our repository is officialy tracking a branch named "master" refering to a
-single commit.
-
-Playing again with Git
-======================
-
-At this point you can come back to the shell, go into the "myrepo" folder and
-type ``git status`` to let Git confirm that this is a regular repository on
-branch "master".
-
-Git will tell you that the file "spam" is deleted, which is normal because
-Git is comparing the repository state with the current working copy. And we
-have absolutely no working copy using Dulwich because we don't need it at
-all!
-
-You can checkout the last state using ``git checkout -f``. The force flag
-will prevent Git from complaining that there are uncommitted changes in the
-working copy.
-
-The file ``spam`` appears and with no surprise contains the same bytes as the
-blob::
-
-  $ cat spam
-  My file content
-
-.. attention:: Remember to recreate the repo object when you modify the
-               repository outside of Dulwich!

=== added file 'docs/tutorial/1-repo.txt'
--- docs/tutorial/1-repo.txt	1970-01-01 00:00:00 +0000
+++ docs/tutorial/1-repo.txt	2010-11-26 15:32:32 +0000
@@ -0,0 +1,28 @@
+The Repository
+==============
+
+After this introduction, let's start directly with code::
+
+  >>> from dulwich.repo import Repo
+
+The access to a repository is through the Repo object. You can open an
+existing repository or you can create a new one. There are two types of Git
+repositories:
+
+  Regular Repositories -- They are the ones you create using ``git init`` and
+  you daily use. They contain a ``.git`` folder.
+
+  Bare Repositories -- There is not ".git" folder. The top-level folder
+  contains itself the "branches", "hooks"... folders. These are used for
+  published repositories (mirrors). They do not have a working tree.
+
+Let's create a folder and turn it into a repository, like ``git init`` would::
+
+  >>> from os import mkdir
+  >>> mkdir("myrepo")
+  >>> repo = Repo.init("myrepo")
+  >>> repo
+  <Repo at 'myrepo'>
+
+You can already look a the structure of the "myrepo/.git" folder, though it
+is mostly empty for now.

=== removed file 'docs/tutorial/2-change-file.txt'
--- docs/tutorial/2-change-file.txt	2009-09-21 20:36:17 +0000
+++ docs/tutorial/2-change-file.txt	1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
-Changing a File and Commit it
-=============================
-
-Now we have a first commit, the next one will show a difference.
-
-As seen in the introduction, it's about making a path in a tree point to a
-new blob. The old blob will remain to compute the diff. The tree is altered
-and the new commit'task is to point to this new version.
-
-In the following examples, we assume we still have the ``repo`` and ``tree``
-object from the previous chapter.
-
-Let's first build the blob::
-
-  >>> spam = Blob.from_string("My new file content\n")
-  >>> spam.id
-  '16ee2682887a962f854ebd25a61db16ef4efe49f'
-
-An alternative is to alter the previously constructed blob object::
-
-  >>> blob.data = "My new file content\n"
-  >>> blob.id
-  '16ee2682887a962f854ebd25a61db16ef4efe49f'
-
-In any case, update the blob id known as "spam". You also have the
-opportunity of changing its mode::
-
-  >>> tree["spam"] = (0100644, spam.id)
-
-Now let's record the change::
-
-  >>> c2 = Commit()
-  >>> c2.tree = tree.id
-  >>> c2.parents = [commit.id]
-  >>> c2.author = c2.committer = author
-  >>> c2.commit_time = c2.author_time = int(time())
-  >>> c2.commit_timezone = c2.author_timezone = tz
-  >>> c2.encoding = "UTF-8"
-  >>> c2.message = 'Changing "spam"'
-
-In this new commit we record the changed tree id, and most important, the
-previous commit as the parent. Parents are actually a list because a commit
-may happen to have several parents after merging branches.
-
-Remain to record this whole new family::
-
-  >>> object_store.add_object(spam)
-  >>> object_store.add_object(tree)
-  >>> object_store.add_object(c2)
-
-You can already ask git to introspect this commit using ``git show`` and the
-value of ``commit.id`` as an argument. You'll see the difference will the
-previous blob recorded as "spam".
-
-You won't see it using git log because the head is still the previous
-commit. It's easy to remedy::
-
-  >>> repo.refs['refs/heads/master'] = commit.id
-
-Now all git tools will work as expected. Though don't forget that Dulwich is
-still open!

=== added file 'docs/tutorial/2-object-store.txt'
--- docs/tutorial/2-object-store.txt	1970-01-01 00:00:00 +0000
+++ docs/tutorial/2-object-store.txt	2010-12-26 00:33:19 +0000
@@ -0,0 +1,184 @@
+The object store
+================
+
+The objects are stored in the ``object store`` of the repository.
+
+  >>> from dulwich.repo import Repo
+  >>> repo = Repo.init("myrepo", mkdir=True)
+
+Initial commit
+--------------
+
+When you use Git, you generally add or modify content. As our repository is
+empty for now, we'll start by adding a new file::
+
+  >>> from dulwich.objects import Blob
+  >>> blob = Blob.from_string("My file content\n")
+  >>> blob.id
+  'c55063a4d5d37aa1af2b2dad3a70aa34dae54dc6'
+
+Of course you could create a blob from an existing file using ``from_file``
+instead.
+
+As said in the introduction, file content is separed from file name. Let's
+give this content a name::
+
+  >>> from dulwich.objects import Tree
+  >>> tree = Tree()
+  >>> tree.add(0100644, "spam", blob.id)
+
+Note that "0100644" is the octal form for a regular file with common
+permissions. You can hardcode them or you can use the ``stat`` module.
+
+The tree state of our repository still needs to be placed in time. That's the
+job of the commit::
+
+  >>> from dulwich.objects import Commit, parse_timezone
+  >>> from time import time
+  >>> commit = Commit()
+  >>> commit.tree = tree.id
+  >>> author = "Your Name <your.email@xxxxxxxxxxx>"
+  >>> commit.author = commit.committer = author
+  >>> commit.commit_time = commit.author_time = int(time())
+  >>> tz = parse_timezone('-0200')[0]
+  >>> commit.commit_timezone = commit.author_timezone = tz
+  >>> commit.encoding = "UTF-8"
+  >>> commit.message = "Initial commit"
+
+Note that the initial commit has no parents.
+
+At this point, the repository is still empty because all operations happen in
+memory. Let's "commit" it.
+
+  >>> object_store = repo.object_store
+  >>> object_store.add_object(blob)
+
+Now the ".git/objects" folder contains a first SHA-1 file. Let's continue
+saving the changes::
+
+  >>> object_store.add_object(tree)
+  >>> object_store.add_object(commit)
+
+Now the physical repository contains three objects but still has no branch.
+Let's create the master branch like Git would::
+
+  >>> repo.refs['refs/heads/master'] = commit.id
+
+The master branch now has a commit where to start. When we commit to master, we
+are also moving HEAD, which is Git's currently checked out branch:
+
+  >>> head = repo.refs['HEAD']
+  >>> head == commit.id
+  True
+  >>> head == repo.refs['refs/heads/master']
+  True
+
+How did that work? As it turns out, HEAD is a special kind of ref called a
+symbolic ref, and it points at master. Most functions on the refs container
+work transparently with symbolic refs, but we can also take a peek inside HEAD:
+
+  >>> repo.refs.read_ref('HEAD')
+  'ref: refs/heads/master'
+
+Normally, you won't need to use read_ref. If you want to change what ref HEAD
+points to, in order to check out another branch, just use set_symbolic_ref.
+
+Now our repository is officially tracking a branch named "master" referring to a
+single commit.
+
+Playing again with Git
+----------------------
+
+At this point you can come back to the shell, go into the "myrepo" folder and
+type ``git status`` to let Git confirm that this is a regular repository on
+branch "master".
+
+Git will tell you that the file "spam" is deleted, which is normal because
+Git is comparing the repository state with the current working copy. And we
+have absolutely no working copy using Dulwich because we don't need it at
+all!
+
+You can checkout the last state using ``git checkout -f``. The force flag
+will prevent Git from complaining that there are uncommitted changes in the
+working copy.
+
+The file ``spam`` appears and with no surprise contains the same bytes as the
+blob::
+
+  $ cat spam
+  My file content
+
+Changing a File and Committing it
+---------------------------------
+
+Now we have a first commit, the next one will show a difference.
+
+As seen in the introduction, it's about making a path in a tree point to a
+new blob. The old blob will remain to compute the diff. The tree is altered
+and the new commit'task is to point to this new version.
+
+Let's first build the blob::
+
+  >>> from dulwich.objects import Blob
+  >>> spam = Blob.from_string("My new file content\n")
+  >>> spam.id
+  '16ee2682887a962f854ebd25a61db16ef4efe49f'
+
+An alternative is to alter the previously constructed blob object::
+
+  >>> blob.data = "My new file content\n"
+  >>> blob.id
+  '16ee2682887a962f854ebd25a61db16ef4efe49f'
+
+In any case, update the blob id known as "spam". You also have the
+opportunity of changing its mode::
+
+  >>> tree["spam"] = (0100644, spam.id)
+
+Now let's record the change::
+
+  >>> from dulwich.objects import Commit
+  >>> from time import time
+  >>> c2 = Commit()
+  >>> c2.tree = tree.id
+  >>> c2.parents = [commit.id]
+  >>> c2.author = c2.committer = "John Doe <john@xxxxxxxxxxx>"
+  >>> c2.commit_time = c2.author_time = int(time())
+  >>> c2.commit_timezone = c2.author_timezone = 0
+  >>> c2.encoding = "UTF-8"
+  >>> c2.message = 'Changing "spam"'
+
+In this new commit we record the changed tree id, and most important, the
+previous commit as the parent. Parents are actually a list because a commit
+may happen to have several parents after merging branches.
+
+Let's put the objects in the object store::
+
+  >>> repo.object_store.add_object(spam)
+  >>> repo.object_store.add_object(tree)
+  >>> repo.object_store.add_object(c2)
+
+You can already ask git to introspect this commit using ``git show`` and the
+value of ``c2.id`` as an argument. You'll see the difference will the
+previous blob recorded as "spam".
+
+The diff between the previous head and the new one can be printed using
+write_tree_diff::
+
+  >>> from dulwich.patch import write_tree_diff
+  >>> import sys
+  >>> write_tree_diff(sys.stdout, repo.object_store, commit.tree, tree.id)
+  diff --git a/spam b/spam
+  index c55063a..16ee268 100644
+  --- a/spam
+  +++ b/spam
+  @@ -1,1 +1,1 @@
+  -My file content
+  +My new file content
+
+You won't see it using git log because the head is still the previous
+commit. It's easy to remedy::
+
+  >>> repo.refs['refs/heads/master'] = c2.id
+
+Now all git tools will work as expected.

=== removed file 'docs/tutorial/3-add-file.txt'
--- docs/tutorial/3-add-file.txt	2009-09-21 20:36:17 +0000
+++ docs/tutorial/3-add-file.txt	1970-01-01 00:00:00 +0000
@@ -1,41 +0,0 @@
-Adding a file
-=============
-
-If you followed well, the next lesson will be straightforward.
-
-We need a new blob::
-
-    >>> ham = Blob.from_string("Another\nmultiline\nfile\n")
-    >>> ham.id
-    'a3b5eda0b83eb8fb6e5dce91ecafda9e97269c70'
-
-But the same tree::
-
-    >>> tree["ham"] = (0100644, spam.id)
-
-And a new commit::
-
-  >>> c3 = Commit()
-  >>> c3.tree = tree.id
-  >>> c3.parents = [commit.id]
-  >>> c3.author = c3.committer = author
-  >>> c3.commit_time = c3.author_time = int(time())
-  >>> c3.commit_timezone = c3.author_timezone = tz
-  >>> c3.encoding = "UTF-8"
-  >>> c3.message = 'Adding "ham"'
-
-Save it all::
-
-    >>> object_store.add_object(spam)
-    >>> object_store.add_object(tree)
-    >>> object_store.add_object(c3)
-
-Update the head::
-
-    >>> repo.refs['refs/heads/master'] = commit.id
-
-A call to ``git show`` will confirm the addition of "spam".
-
-Remember you can also call ``git checkout -f`` to make it appear.
-
-Well... Adding "spam" was not such a good idea... We'll remove it.

=== added file 'docs/tutorial/3-conclusion.txt'
--- docs/tutorial/3-conclusion.txt	1970-01-01 00:00:00 +0000
+++ docs/tutorial/3-conclusion.txt	2010-11-26 15:32:32 +0000
@@ -0,0 +1,11 @@
+Conclusion
+==========
+
+This tutorial currently only covers a small (but important) part of Dulwich.
+It still needs to be extended to cover packs, tags, refs, reflogs and network
+communication.
+
+Dulwich is abstracting much of the Git plumbing, so there would be more to
+see.
+
+For now, that's all folks!

=== removed file 'docs/tutorial/4-remove-file.txt'
--- docs/tutorial/4-remove-file.txt	2009-09-21 20:36:17 +0000
+++ docs/tutorial/4-remove-file.txt	1970-01-01 00:00:00 +0000
@@ -1,30 +0,0 @@
-Removing a file
-===============
-
-Removing a file just means removing its entry in the tree. The blob won't be
-deleted because Git tries to preserve the history of your repository.
-
-It's all pythonic::
-
-    >>> del tree["ham"]
-
-  >>> c4 = Commit()
-  >>> c4.tree = tree.id
-  >>> c4.parents = [commit.id]
-  >>> c4.author = c4.committer = author
-  >>> c4.commit_time = c4.author_time = int(time())
-  >>> c4.commit_timezone = c4.author_timezone = tz
-  >>> c4.encoding = "UTF-8"
-  >>> c4.message = 'Removing "ham"'
-
-Here we only have the new tree and the commit to save::
-
-    >>> object_store.add_object(spam)
-    >>> object_store.add_object(tree)
-    >>> object_store.add_object(c4)
-
-And of course update the head::
-
-    >>> repo.refs['refs/heads/master'] = commit.id
-
-If you don't trust me, ask ``git show``. ;-)

=== removed file 'docs/tutorial/5-rename-file.txt'
--- docs/tutorial/5-rename-file.txt	2009-09-21 20:36:17 +0000
+++ docs/tutorial/5-rename-file.txt	1970-01-01 00:00:00 +0000
@@ -1,33 +0,0 @@
-Renaming a file
-===============
-
-Remember you learned that the file name and content are distinct. So renaming
-a file is just about associating a blob id to a new name. We won't store more
-content, and the operation will be painless.
-
-Let's transfer the blob id from the old name to the new one::
-
-    >>> tree["eggs"] = tree["spam"]
-    >>> del tree["spam"]
-
-As usual, we need a commit to store the new tree id::
-
-  >>> c5 = Commit()
-  >>> c5.tree = tree.id
-  >>> c5.parents = [commit.id]
-  >>> c5.author = c5.committer = author
-  >>> c5.commit_time = c5.author_time = int(time())
-  >>> c5.commit_timezone = c5.author_timezone = tz
-  >>> c5.encoding = "UTF-8"
-  >>> c5.message = 'Rename "spam" to "eggs"'
-
-As for a deletion, we only have a tree and a commit to save::
-
-    >>> object_store.add_object(tree)
-    >>> object_store.add_object(c5)
-
-Remains to make the head bleeding-edge::
-
-    >>> repo.refs['refs/heads/master'] = commit.id
-
-As a last exercise, see how ``git show`` illustrates it.

=== removed file 'docs/tutorial/6-conclusion.txt'
--- docs/tutorial/6-conclusion.txt	2009-09-21 20:36:17 +0000
+++ docs/tutorial/6-conclusion.txt	1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@
-Conclusion
-==========
-
-You'll find the ``test.py`` program with some tips I use to ease generating
-objects.
-
-You can also make Tag objects, but this is left as a exercise to the reader.
-
-Dulwich is abstracting  much of the Git plumbing, so there would be more to
-see.
-
-Dulwich is also able to clone and push repositories.
-
-That's all folks!

=== modified file 'docs/tutorial/index.txt'
--- docs/tutorial/index.txt	2009-09-21 20:36:17 +0000
+++ docs/tutorial/index.txt	2010-11-26 15:32:32 +0000
@@ -5,9 +5,6 @@
 .. contents::
 
 .. include:: 0-introduction.txt
-.. include:: 1-initial-commit.txt
-.. include:: 2-change-file.txt
-.. include:: 3-add-file.txt
-.. include:: 4-remove-file.txt
-.. include:: 5-rename-file.txt
-.. include:: 6-conclusion.txt
+.. include:: 1-repo.txt
+.. include:: 2-object-store.txt
+.. include:: 3-conclusion.txt

=== removed file 'docs/tutorial/test.py'
--- docs/tutorial/test.py	2009-09-21 20:36:17 +0000
+++ docs/tutorial/test.py	1970-01-01 00:00:00 +0000
@@ -1,178 +0,0 @@
-#!/usr/bin/env python
-# -*- encoding: UTF-8 -*-
-
-# Import from the Standard Library
-from os import F_OK, access, mkdir
-from pprint import pprint
-from shutil import rmtree
-from subprocess import call
-from time import time
-
-# Import from dulwich
-from dulwich.repo import Repo
-from dulwich.objects import Blob, Tree, Commit, parse_timezone
-
-
-DIRNAME = "myrepo"
-AUTHOR = "Your Name <your.email@xxxxxxxxxxx>"
-TZ = parse_timezone('-200')
-ENCODING = "UTF-8"
-
-
-def make_commit(repo, tree_id, message):
-    """Build a commit object on the same pattern. Only changing values are
-    required as parameters.
-    """
-    commit = Commit()
-    try:
-        commit.parents = [repo.head()]
-    except KeyError:
-        # The initial commit has no parent
-        pass
-    commit.tree = tree_id
-    commit.message = message
-    commit.author = commit.committer = AUTHOR
-    commit.commit_time = commit.author_time = int(time())
-    commit.commit_timezone = commit.author_timezone = TZ
-    commit.encoding = ENCODING
-    return commit
-
-
-
-def make_tree(repo):
-    """Return the last known tree.
-    """
-    commit_id = repo.head()
-    commit = repo.commit(commit_id)
-    tree_id = commit.tree
-    return repo.tree(tree_id)
-
-
-
-def update_master(repo, commit_id):
-    repo.refs['refs/heads/master'] = commit_id
-
-
-
-def initial_commit(repo):
-    # Add file content
-    blob = Blob.from_string("My file content\n")
-    # Add file
-    tree = Tree()
-    tree.add(0100644, "spam", blob.id)
-    # Set commit
-    commit = make_commit(repo, tree.id, "Initial commit")
-    # Initial commit
-    object_store = repo.object_store
-    object_store.add_object(blob)
-    object_store.add_object(tree)
-    object_store.add_object(commit)
-    # Update master
-    update_master(repo, commit.id)
-    # Set the master branch as the default
-    repo.refs['HEAD'] = 'ref: refs/heads/master'
-
-
-
-def test_change(repo):
-    tree = make_tree(repo)
-    # Change a file
-    spam = Blob.from_string("My new file content\n")
-    tree.add(0100644, "spam", spam.id)
-    # Set commit
-    commit = make_commit(repo, tree.id, "Change spam")
-    # Second commit
-    object_store = repo.object_store
-    object_store.add_object(spam)
-    object_store.add_object(tree)
-    object_store.add_object(commit)
-    # Update master
-    update_master(repo, commit.id)
-
-
-
-def test_add(repo):
-    tree = make_tree(repo)
-    # Add another file
-    ham = Blob.from_string("Another\nmultiline\nfile\n")
-    tree.add(0100644, "ham", ham.id)
-    # Set commit
-    commit = make_commit(repo, tree.id, "Add ham")
-    # Second commit
-    object_store = repo.object_store
-    object_store.add_object(ham)
-    object_store.add_object(tree)
-    object_store.add_object(commit)
-    # Update master
-    update_master(repo, commit.id)
-
-
-
-def test_remove(repo):
-    tree = make_tree(repo)
-    # Remove a file
-    del tree["ham"]
-    # Set commit
-    commit = make_commit(repo, tree.id, 'Remove "ham"')
-    # Third commit
-    # No blob change, just tree operation
-    object_store = repo.object_store
-    object_store.add_object(tree)
-    object_store.add_object(commit)
-    # Update master
-    update_master(repo, commit.id)
-
-
-
-def test_rename(repo):
-    tree = make_tree(repo)
-    # Rename a file
-    tree["eggs"] = tree["spam"]
-    del tree["spam"]
-    # Set commit
-    commit = make_commit(repo, tree.id, 'Rename "spam" to "eggs"')
-    # Fourth commit
-    # No blob change, just tree operation
-    object_store = repo.object_store
-    object_store.add_object(tree)
-    object_store.add_object(commit)
-    # Update master
-    update_master(repo, commit.id)
-
-
-
-def test_history(repo):
-    pprint(repo.revision_history(repo.head()))
-
-
-
-def test_file(repo):
-    tree = make_tree(repo)
-    print "entries", tree.entries()
-    mode, blob_id = tree["eggs"]
-    blob = repo.get_blob(blob_id)
-    print "eggs", repr(blob.data)
-
-
-
-if __name__ == '__main__':
-    # Creating the repository
-    if access(DIRNAME, F_OK):
-        rmtree(DIRNAME)
-    mkdir(DIRNAME)
-    repo = Repo.init(DIRNAME)
-    initial_commit(repo)
-    test_change(repo)
-    test_add(repo)
-    test_remove(repo)
-    test_rename(repo)
-    last_commit_id = repo.head()
-    call(['git', 'gc'], cwd=DIRNAME)
-    # Re-load the repo
-    del repo
-    repo = Repo(DIRNAME)
-    # XXX the ref was removed and dulwich doesn't know where to read it
-    update_master(repo, last_commit_id)
-    assert last_commit_id == repo.head()
-    test_history(repo)
-    test_file(repo)

=== modified file 'dulwich/__init__.py'
--- dulwich/__init__.py	2009-10-07 09:29:12 +0000
+++ dulwich/__init__.py	2011-01-14 18:33:07 +0000
@@ -1,18 +1,18 @@
 # __init__.py -- The git module of dulwich
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
 # Copyright (C) 2008 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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 
+# 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,
@@ -21,10 +21,6 @@
 
 """Python implementation of the Git file formats and protocols."""
 
-
-import client
-import protocol
-import repo
-import server
-
-__version__ = (0, 4, 1)
+from dulwich import (client, protocol, repo, server)
+
+__version__ = (0, 7, 0)

=== added file 'dulwich/_compat.py'
--- dulwich/_compat.py	1970-01-01 00:00:00 +0000
+++ dulwich/_compat.py	2010-12-19 15:56:03 +0000
@@ -0,0 +1,230 @@
+# _compat.py -- For dealing with python2.4 oddness
+# Copyright (C) 2008 Canonical Ltd.
+#
+# 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) a later version.
+#
+# 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.
+
+"""Misc utilities to work with python <2.6.
+
+These utilities can all be deleted when dulwich decides it wants to stop
+support for python <2.6.
+"""
+try:
+    import hashlib
+except ImportError:
+    import sha
+
+try:
+    from urlparse import parse_qs
+except ImportError:
+    from cgi import parse_qs
+
+try:
+    from os import SEEK_END
+except ImportError:
+    SEEK_END = 2
+
+import struct
+
+
+class defaultdict(dict):
+    """A python 2.4 equivalent of collections.defaultdict."""
+
+    def __init__(self, default_factory=None, *a, **kw):
+        if (default_factory is not None and
+            not hasattr(default_factory, '__call__')):
+            raise TypeError('first argument must be callable')
+        dict.__init__(self, *a, **kw)
+        self.default_factory = default_factory
+
+    def __getitem__(self, key):
+        try:
+            return dict.__getitem__(self, key)
+        except KeyError:
+            return self.__missing__(key)
+
+    def __missing__(self, key):
+        if self.default_factory is None:
+            raise KeyError(key)
+        self[key] = value = self.default_factory()
+        return value
+
+    def __reduce__(self):
+        if self.default_factory is None:
+            args = tuple()
+        else:
+            args = self.default_factory,
+        return type(self), args, None, None, self.items()
+
+    def copy(self):
+        return self.__copy__()
+
+    def __copy__(self):
+        return type(self)(self.default_factory, self)
+
+    def __deepcopy__(self, memo):
+        import copy
+        return type(self)(self.default_factory,
+                          copy.deepcopy(self.items()))
+    def __repr__(self):
+        return 'defaultdict(%s, %s)' % (self.default_factory,
+                                        dict.__repr__(self))
+
+
+def make_sha(source=''):
+    """A python2.4 workaround for the sha/hashlib module fiasco."""
+    try:
+        return hashlib.sha1(source)
+    except NameError:
+        sha1 = sha.sha(source)
+        return sha1
+
+
+def unpack_from(fmt, buf, offset=0):
+    """A python2.4 workaround for struct missing unpack_from."""
+    try:
+        return struct.unpack_from(fmt, buf, offset)
+    except AttributeError:
+        b = buf[offset:offset+struct.calcsize(fmt)]
+        return struct.unpack(fmt, b)
+
+
+try:
+    from itertools import permutations
+except ImportError:
+    # Implementation of permutations from Python 2.6 documentation:
+    # http://docs.python.org/2.6/library/itertools.html#itertools.permutations
+    # Copyright (c) 2001-2010 Python Software Foundation; All Rights Reserved
+    # Modified syntax slightly to run under Python 2.4.
+    def permutations(iterable, r=None):
+        # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
+        # permutations(range(3)) --> 012 021 102 120 201 210
+        pool = tuple(iterable)
+        n = len(pool)
+        if r is None:
+            r = n
+        if r > n:
+            return
+        indices = range(n)
+        cycles = range(n, n-r, -1)
+        yield tuple(pool[i] for i in indices[:r])
+        while n:
+            for i in reversed(range(r)):
+                cycles[i] -= 1
+                if cycles[i] == 0:
+                    indices[i:] = indices[i+1:] + indices[i:i+1]
+                    cycles[i] = n - i
+                else:
+                    j = cycles[i]
+                    indices[i], indices[-j] = indices[-j], indices[i]
+                    yield tuple(pool[i] for i in indices[:r])
+                    break
+            else:
+                return
+
+
+try:
+    from collections import namedtuple
+
+    TreeEntryTuple = namedtuple('TreeEntryTuple', ['path', 'mode', 'sha'])
+    TreeChangeTuple = namedtuple('TreeChangeTuple', ['type', 'old', 'new'])
+except ImportError:
+    # Provide manual implementations of namedtuples for Python <2.5.
+    # If the class definitions change, be sure to keep these in sync by running
+    # namedtuple(..., verbose=True) in a recent Python and pasting the output.
+
+    # Necessary globals go here.
+    _tuple = tuple
+    _property = property
+    from operator import itemgetter as _itemgetter
+
+    class TreeEntryTuple(tuple):
+            'TreeEntryTuple(path, mode, sha)'
+
+            __slots__ = ()
+
+            _fields = ('path', 'mode', 'sha')
+
+            def __new__(_cls, path, mode, sha):
+                return _tuple.__new__(_cls, (path, mode, sha))
+
+            @classmethod
+            def _make(cls, iterable, new=tuple.__new__, len=len):
+                'Make a new TreeEntryTuple object from a sequence or iterable'
+                result = new(cls, iterable)
+                if len(result) != 3:
+                    raise TypeError('Expected 3 arguments, got %d' % len(result))
+                return result
+
+            def __repr__(self):
+                return 'TreeEntryTuple(path=%r, mode=%r, sha=%r)' % self
+
+            def _asdict(t):
+                'Return a new dict which maps field names to their values'
+                return {'path': t[0], 'mode': t[1], 'sha': t[2]}
+
+            def _replace(_self, **kwds):
+                'Return a new TreeEntryTuple object replacing specified fields with new values'
+                result = _self._make(map(kwds.pop, ('path', 'mode', 'sha'), _self))
+                if kwds:
+                    raise ValueError('Got unexpected field names: %r' % kwds.keys())
+                return result
+
+            def __getnewargs__(self):
+                return tuple(self)
+
+            path = _property(_itemgetter(0))
+            mode = _property(_itemgetter(1))
+            sha = _property(_itemgetter(2))
+
+
+    class TreeChangeTuple(tuple):
+            'TreeChangeTuple(type, old, new)'
+
+            __slots__ = ()
+
+            _fields = ('type', 'old', 'new')
+
+            def __new__(_cls, type, old, new):
+                return _tuple.__new__(_cls, (type, old, new))
+
+            @classmethod
+            def _make(cls, iterable, new=tuple.__new__, len=len):
+                'Make a new TreeChangeTuple object from a sequence or iterable'
+                result = new(cls, iterable)
+                if len(result) != 3:
+                    raise TypeError('Expected 3 arguments, got %d' % len(result))
+                return result
+
+            def __repr__(self):
+                return 'TreeChangeTuple(type=%r, old=%r, new=%r)' % self
+
+            def _asdict(t):
+                'Return a new dict which maps field names to their values'
+                return {'type': t[0], 'old': t[1], 'new': t[2]}
+
+            def _replace(_self, **kwds):
+                'Return a new TreeChangeTuple object replacing specified fields with new values'
+                result = _self._make(map(kwds.pop, ('type', 'old', 'new'), _self))
+                if kwds:
+                    raise ValueError('Got unexpected field names: %r' % kwds.keys())
+                return result
+
+            def __getnewargs__(self):
+                return tuple(self)
+
+            type = _property(_itemgetter(0))
+            old = _property(_itemgetter(1))
+            new = _property(_itemgetter(2))

=== added file 'dulwich/_diff_tree.c'
--- dulwich/_diff_tree.c	1970-01-01 00:00:00 +0000
+++ dulwich/_diff_tree.c	2010-12-19 17:58:02 +0000
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * 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) a 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.
+ */
+
+#include <Python.h>
+#include <sys/stat.h>
+
+#if (PY_VERSION_HEX < 0x02050000)
+typedef int Py_ssize_t;
+#endif
+
+#if (PY_VERSION_HEX < 0x02060000)
+#define Py_SIZE(ob)             (((PyVarObject*)(ob))->ob_size)
+#endif
+
+static PyObject *tree_entry_cls = NULL, *null_entry = NULL,
+	*defaultdict_cls = NULL, *int_cls = NULL;
+static int block_size;
+
+/**
+ * Free an array of PyObject pointers, decrementing any references.
+ */
+static void free_objects(PyObject **objs, Py_ssize_t n)
+{
+	Py_ssize_t i;
+	for (i = 0; i < n; i++)
+		Py_XDECREF(objs[i]);
+	PyMem_Free(objs);
+}
+
+/**
+ * Get the entries of a tree, prepending the given path.
+ *
+ * :param path: The path to prepend, without trailing slashes.
+ * :param path_len: The length of path.
+ * :param tree: The Tree object to iterate.
+ * :param n: Set to the length of result.
+ * :return: A (C) array of PyObject pointers to TreeEntry objects for each path
+ *     in tree.
+ */
+static PyObject **tree_entries(char *path, Py_ssize_t path_len, PyObject *tree,
+		Py_ssize_t *n)
+{
+	PyObject *iteritems, *items, **result = NULL;
+	PyObject *old_entry, *name, *sha;
+	Py_ssize_t i = 0, name_len, new_path_len;
+	char *new_path;
+
+	if (tree == Py_None) {
+		*n = 0;
+		result = PyMem_New(PyObject*, 0);
+		if (!result) {
+			PyErr_SetNone(PyExc_MemoryError);
+			return NULL;
+		}
+		return result;
+	}
+
+	iteritems = PyObject_GetAttrString(tree, "iteritems");
+	if (!iteritems)
+		return NULL;
+	items = PyObject_CallFunctionObjArgs(iteritems, Py_True, NULL);
+	Py_DECREF(iteritems);
+	if (!items) {
+		return NULL;
+	}
+	/* The C implementation of iteritems returns a list, so depend on that. */
+	if (!PyList_Check(items)) {
+		PyErr_SetString(PyExc_TypeError,
+			"Tree.iteritems() did not return a list");
+		return NULL;
+	}
+
+	*n = PyList_Size(items);
+	result = PyMem_New(PyObject*, *n);
+	if (!result) {
+		PyErr_SetNone(PyExc_MemoryError);
+		goto error;
+	}
+	for (i = 0; i < *n; i++) {
+		old_entry = PyList_GetItem(items, i);
+		if (!old_entry)
+			goto error;
+		sha = PyTuple_GetItem(old_entry, 2);
+		if (!sha)
+			goto error;
+		name = PyTuple_GET_ITEM(old_entry, 0);
+		name_len = PyString_Size(name);
+		if (PyErr_Occurred())
+			goto error;
+
+		new_path_len = name_len;
+		if (path_len)
+			new_path_len += path_len + 1;
+		new_path = PyMem_Malloc(new_path_len);
+		if (!new_path) {
+			PyErr_SetNone(PyExc_MemoryError);
+			goto error;
+		}
+		if (path_len) {
+			memcpy(new_path, path, path_len);
+			new_path[path_len] = '/';
+			memcpy(new_path + path_len + 1, PyString_AS_STRING(name), name_len);
+		} else {
+			memcpy(new_path, PyString_AS_STRING(name), name_len);
+		}
+
+		result[i] = PyObject_CallFunction(tree_entry_cls, "s#OO", new_path,
+			new_path_len, PyTuple_GET_ITEM(old_entry, 1), sha);
+		PyMem_Free(new_path);
+		if (!result[i]) {
+			goto error;
+		}
+	}
+	Py_DECREF(items);
+	return result;
+
+error:
+	free_objects(result, i);
+	Py_DECREF(items);
+	return NULL;
+}
+
+/**
+ * Use strcmp to compare the paths of two TreeEntry objects.
+ */
+static int entry_path_cmp(PyObject *entry1, PyObject *entry2)
+{
+	PyObject *path1 = NULL, *path2 = NULL;
+	int result = 0;
+
+	path1 = PyObject_GetAttrString(entry1, "path");
+	if (!path1)
+		goto done;
+	if (!PyString_Check(path1)) {
+		PyErr_SetString(PyExc_TypeError, "path is not a string");
+		goto done;
+	}
+
+	path2 = PyObject_GetAttrString(entry2, "path");
+	if (!path2)
+		goto done;
+	if (!PyString_Check(path2)) {
+		PyErr_SetString(PyExc_TypeError, "path is not a string");
+		goto done;
+	}
+
+	result = strcmp(PyString_AS_STRING(path1), PyString_AS_STRING(path2));
+
+done:
+	Py_XDECREF(path1);
+	Py_XDECREF(path2);
+	return result;
+}
+
+static PyObject *py_merge_entries(PyObject *self, PyObject *args)
+{
+	PyObject *path, *tree1, *tree2, **entries1 = NULL, **entries2 = NULL;
+	PyObject *e1, *e2, *pair, *result = NULL;
+	Py_ssize_t path_len, n1 = 0, n2 = 0, i1 = 0, i2 = 0;
+	char *path_str;
+	int cmp;
+
+	if (!PyArg_ParseTuple(args, "OOO", &path, &tree1, &tree2))
+		return NULL;
+
+	path_str = PyString_AsString(path);
+	if (!path_str) {
+		PyErr_SetString(PyExc_TypeError, "path is not a string");
+		return NULL;
+	}
+	path_len = PyString_GET_SIZE(path);
+
+	entries1 = tree_entries(path_str, path_len, tree1, &n1);
+	if (!entries1)
+		goto error;
+	entries2 = tree_entries(path_str, path_len, tree2, &n2);
+	if (!entries2)
+		goto error;
+
+	result = PyList_New(n1 + n2);
+	if (!result)
+		goto error;
+	/* PyList_New sets the len of the list, not its allocated size, so we
+	 * need to trim it to the size we actually use. */
+	Py_SIZE(result) = 0;
+
+	while (i1 < n1 && i2 < n2) {
+		cmp = entry_path_cmp(entries1[i1], entries2[i2]);
+		if (PyErr_Occurred())
+			goto error;
+		if (!cmp) {
+			e1 = entries1[i1++];
+			e2 = entries2[i2++];
+		} else if (cmp < 0) {
+			e1 = entries1[i1++];
+			e2 = null_entry;
+		} else {
+			e1 = null_entry;
+			e2 = entries2[i2++];
+		}
+		pair = PyTuple_Pack(2, e1, e2);
+		if (!pair)
+			goto error;
+		PyList_SET_ITEM(result, Py_SIZE(result)++, pair);
+	}
+
+	while (i1 < n1) {
+		pair = PyTuple_Pack(2, entries1[i1++], null_entry);
+		if (!pair)
+			goto error;
+		PyList_SET_ITEM(result, Py_SIZE(result)++, pair);
+	}
+	while (i2 < n2) {
+		pair = PyTuple_Pack(2, null_entry, entries2[i2++]);
+		if (!pair)
+			goto error;
+		PyList_SET_ITEM(result, Py_SIZE(result)++, pair);
+	}
+	goto done;
+
+error:
+	Py_XDECREF(result);
+	result = NULL;
+
+done:
+	free_objects(entries1, n1);
+	free_objects(entries2, n2);
+	return result;
+}
+
+static PyObject *py_is_tree(PyObject *self, PyObject *args)
+{
+	PyObject *entry, *mode, *result;
+	long lmode;
+
+	if (!PyArg_ParseTuple(args, "O", &entry))
+		return NULL;
+
+	mode = PyObject_GetAttrString(entry, "mode");
+	if (!mode)
+		return NULL;
+
+	if (mode == Py_None) {
+		result = Py_False;
+	} else {
+		lmode = PyInt_AsLong(mode);
+		if (lmode == -1 && PyErr_Occurred()) {
+			Py_DECREF(mode);
+			return NULL;
+		}
+		result = PyBool_FromLong(S_ISDIR((mode_t)lmode));
+	}
+	Py_INCREF(result);
+	Py_DECREF(mode);
+	return result;
+}
+
+static int add_hash(PyObject *get, PyObject *set, char *str, int n)
+{
+	PyObject *str_obj = NULL, *hash_obj = NULL, *value = NULL,
+		*set_value = NULL;
+	long hash;
+
+	/* It would be nice to hash without copying str into a PyString, but that
+	 * isn't exposed by the API. */
+	str_obj = PyString_FromStringAndSize(str, n);
+	if (!str_obj)
+		goto error;
+	hash = PyObject_Hash(str_obj);
+	if (hash == -1)
+		goto error;
+	hash_obj = PyInt_FromLong(hash);
+	if (!hash_obj)
+		goto error;
+
+	value = PyObject_CallFunctionObjArgs(get, hash_obj, NULL);
+	if (!value)
+		goto error;
+	set_value = PyObject_CallFunction(set, "(Ol)", hash_obj,
+		PyInt_AS_LONG(value) + n);
+	if (!set_value)
+		goto error;
+
+	Py_DECREF(str_obj);
+	Py_DECREF(hash_obj);
+	Py_DECREF(value);
+	Py_DECREF(set_value);
+	return 0;
+
+error:
+	Py_XDECREF(str_obj);
+	Py_XDECREF(hash_obj);
+	Py_XDECREF(value);
+	Py_XDECREF(set_value);
+	return -1;
+}
+
+static PyObject *py_count_blocks(PyObject *self, PyObject *args)
+{
+	PyObject *obj, *chunks = NULL, *chunk, *counts = NULL, *get = NULL,
+		*set = NULL;
+	char *chunk_str, *block = NULL;
+	Py_ssize_t num_chunks, chunk_len;
+	int i, j, n = 0;
+	char c;
+
+	if (!PyArg_ParseTuple(args, "O", &obj))
+		goto error;
+
+	counts = PyObject_CallFunctionObjArgs(defaultdict_cls, int_cls, NULL);
+	if (!counts)
+		goto error;
+	get = PyObject_GetAttrString(counts, "__getitem__");
+	set = PyObject_GetAttrString(counts, "__setitem__");
+
+	chunks = PyObject_CallMethod(obj, "as_raw_chunks", NULL);
+	if (!chunks)
+		goto error;
+	if (!PyList_Check(chunks)) {
+		PyErr_SetString(PyExc_TypeError,
+			"as_raw_chunks() did not return a list");
+		goto error;
+	}
+	num_chunks = PyList_GET_SIZE(chunks);
+	block = PyMem_New(char, block_size);
+	if (!block) {
+		PyErr_SetNone(PyExc_MemoryError);
+		goto error;
+	}
+
+	for (i = 0; i < num_chunks; i++) {
+		chunk = PyList_GET_ITEM(chunks, i);
+		if (!PyString_Check(chunk)) {
+			PyErr_SetString(PyExc_TypeError, "chunk is not a string");
+			goto error;
+		}
+		if (PyString_AsStringAndSize(chunk, &chunk_str, &chunk_len) == -1)
+			goto error;
+
+		for (j = 0; j < chunk_len; j++) {
+			c = chunk_str[j];
+			block[n++] = c;
+			if (c == '\n' || n == block_size) {
+				if (add_hash(get, set, block, n) == -1)
+					goto error;
+				n = 0;
+			}
+		}
+	}
+	if (n && add_hash(get, set, block, n) == -1)
+		goto error;
+
+	Py_DECREF(chunks);
+	Py_DECREF(get);
+	Py_DECREF(set);
+	PyMem_Free(block);
+	return counts;
+
+error:
+	Py_XDECREF(chunks);
+	Py_XDECREF(get);
+	Py_XDECREF(set);
+	Py_XDECREF(counts);
+	PyMem_Free(block);
+	return NULL;
+}
+
+static PyMethodDef py_diff_tree_methods[] = {
+	{ "_is_tree", (PyCFunction)py_is_tree, METH_VARARGS, NULL },
+	{ "_merge_entries", (PyCFunction)py_merge_entries, METH_VARARGS, NULL },
+	{ "_count_blocks", (PyCFunction)py_count_blocks, METH_VARARGS, NULL },
+	{ NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC
+init_diff_tree(void)
+{
+	PyObject *m, *objects_mod = NULL, *diff_tree_mod = NULL;
+        PyObject *block_size_obj = NULL;
+	m = Py_InitModule("_diff_tree", py_diff_tree_methods);
+	if (!m)
+		goto error;
+
+	objects_mod = PyImport_ImportModule("dulwich.objects");
+	if (!objects_mod)
+		goto error;
+
+	tree_entry_cls = PyObject_GetAttrString(objects_mod, "TreeEntry");
+	Py_DECREF(objects_mod);
+	if (!tree_entry_cls)
+		goto error;
+
+	diff_tree_mod = PyImport_ImportModule("dulwich.diff_tree");
+	if (!diff_tree_mod)
+		goto error;
+
+	null_entry = PyObject_GetAttrString(diff_tree_mod, "_NULL_ENTRY");
+	if (!null_entry)
+		goto error;
+
+	block_size_obj = PyObject_GetAttrString(diff_tree_mod, "_BLOCK_SIZE");
+	if (!block_size_obj)
+		goto error;
+	block_size = (int)PyInt_AsLong(block_size_obj);
+
+	if (PyErr_Occurred())
+		goto error;
+
+	defaultdict_cls = PyObject_GetAttrString(diff_tree_mod, "defaultdict");
+	if (!defaultdict_cls)
+		goto error;
+
+	/* This is kind of hacky, but I don't know of a better way to get the
+	 * PyObject* version of int. */
+	int_cls = PyDict_GetItemString(PyEval_GetBuiltins(), "int");
+	if (!int_cls) {
+		PyErr_SetString(PyExc_NameError, "int");
+		goto error;
+	}
+
+	Py_DECREF(objects_mod);
+	Py_DECREF(diff_tree_mod);
+	return;
+
+error:
+	Py_XDECREF(objects_mod);
+	Py_XDECREF(diff_tree_mod);
+	Py_XDECREF(null_entry);
+	Py_XDECREF(block_size_obj);
+	Py_XDECREF(defaultdict_cls);
+	Py_XDECREF(int_cls);
+	return;
+}

=== modified file 'dulwich/_objects.c'
--- dulwich/_objects.c	2009-07-24 08:42:58 +0000
+++ dulwich/_objects.c	2010-12-11 02:09:50 +0000
@@ -1,16 +1,16 @@
-/* 
+/*
  * Copyright (C) 2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
  *
  * 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) a 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,
@@ -18,9 +18,26 @@
  */
 
 #include <Python.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#if (PY_VERSION_HEX < 0x02050000)
+typedef int Py_ssize_t;
+#endif
+
+#if defined(__MINGW32_VERSION) || defined(__APPLE__)
+size_t strnlen(char *text, size_t maxlen)
+{
+	const char *last = memchr(text, '\0', maxlen);
+	return last ? (size_t) (last - text) : maxlen;
+}
+#endif
 
 #define bytehex(x) (((x)<0xa)?('0'+(x)):('a'-0xa+(x)))
 
+static PyObject *tree_entry_cls;
+static PyObject *object_format_exception_cls;
+
 static PyObject *sha_to_pyhex(const unsigned char *sha)
 {
 	char hexsha[41];
@@ -29,39 +46,55 @@
 		hexsha[i*2] = bytehex((sha[i] & 0xF0) >> 4);
 		hexsha[i*2+1] = bytehex(sha[i] & 0x0F);
 	}
-	
+
 	return PyString_FromStringAndSize(hexsha, 40);
 }
 
-static PyObject *py_parse_tree(PyObject *self, PyObject *args)
+static PyObject *py_parse_tree(PyObject *self, PyObject *args, PyObject *kw)
 {
-	char *text, *end;
-	int len, namelen;
-	PyObject *ret, *item, *name;
+	char *text, *start, *end;
+	int len, namelen, strict;
+	PyObject *ret, *item, *name, *py_strict = NULL;
+	static char *kwlist[] = {"text", "strict", NULL};
 
-	if (!PyArg_ParseTuple(args, "s#", &text, &len))
+	if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|O", kwlist,
+	                                 &text, &len, &py_strict))
 		return NULL;
 
-	ret = PyDict_New();
+
+	strict = py_strict ?  PyObject_IsTrue(py_strict) : 0;
+
+	/* TODO: currently this returns a list; if memory usage is a concern,
+	 * consider rewriting as a custom iterator object */
+	ret = PyList_New(0);
+
 	if (ret == NULL) {
 		return NULL;
 	}
 
+	start = text;
 	end = text + len;
 
-    while (text < end) {
-        long mode;
+	while (text < end) {
+		long mode;
+		if (strict && text[0] == '0') {
+			PyErr_SetString(object_format_exception_cls,
+			                "Illegal leading zero on mode");
+			Py_DECREF(ret);
+			return NULL;
+		}
+
 		mode = strtol(text, &text, 8);
 
 		if (*text != ' ') {
-			PyErr_SetString(PyExc_RuntimeError, "Expected space");
+			PyErr_SetString(PyExc_ValueError, "Expected space");
 			Py_DECREF(ret);
 			return NULL;
 		}
 
 		text++;
 
-        namelen = strlen(text);
+		namelen = strnlen(text, len - (text - start));
 
 		name = PyString_FromStringAndSize(text, namelen);
 		if (name == NULL) {
@@ -69,36 +102,187 @@
 			return NULL;
 		}
 
-        item = Py_BuildValue("(lN)", mode, sha_to_pyhex((unsigned char *)text+namelen+1));
-        if (item == NULL) {
-            Py_DECREF(ret);
-			Py_DECREF(name);
-            return NULL;
-        }
-		if (PyDict_SetItem(ret, name, item) == -1) {
+		if (text + namelen + 20 >= end) {
+			PyErr_SetString(PyExc_ValueError, "SHA truncated");
+			Py_DECREF(ret);
+			Py_DECREF(name);
+			return NULL;
+		}
+
+		item = Py_BuildValue("(NlN)", name, mode,
+		                     sha_to_pyhex((unsigned char *)text+namelen+1));
+		if (item == NULL) {
+			Py_DECREF(ret);
+			Py_DECREF(name);
+			return NULL;
+		}
+		if (PyList_Append(ret, item) == -1) {
 			Py_DECREF(ret);
 			Py_DECREF(item);
 			return NULL;
 		}
-		Py_DECREF(name);
 		Py_DECREF(item);
 
 		text += namelen+21;
-    }
-
-    return ret;
+	}
+
+	return ret;
+}
+
+struct tree_item {
+	const char *name;
+	int mode;
+	PyObject *tuple;
+};
+
+int cmp_tree_item(const void *_a, const void *_b)
+{
+	const struct tree_item *a = _a, *b = _b;
+	const char *remain_a, *remain_b;
+	int ret, common;
+	if (strlen(a->name) > strlen(b->name)) {
+		common = strlen(b->name);
+		remain_a = a->name + common;
+		remain_b = (S_ISDIR(b->mode)?"/":"");
+	} else if (strlen(b->name) > strlen(a->name)) {
+		common = strlen(a->name);
+		remain_a = (S_ISDIR(a->mode)?"/":"");
+		remain_b = b->name + common;
+	} else { /* strlen(a->name) == strlen(b->name) */
+		common = 0;
+		remain_a = a->name;
+		remain_b = b->name;
+	}
+	ret = strncmp(a->name, b->name, common);
+	if (ret != 0)
+		return ret;
+	return strcmp(remain_a, remain_b);
+}
+
+int cmp_tree_item_name_order(const void *_a, const void *_b) {
+	const struct tree_item *a = _a, *b = _b;
+	return strcmp(a->name, b->name);
+}
+
+static PyObject *py_sorted_tree_items(PyObject *self, PyObject *args)
+{
+	struct tree_item *qsort_entries = NULL;
+	int name_order, num_entries, n = 0, i;
+	PyObject *entries, *py_name_order, *ret, *key, *value, *py_mode, *py_sha;
+	Py_ssize_t pos = 0;
+	int (*cmp)(const void *, const void *);
+
+	if (!PyArg_ParseTuple(args, "OO", &entries, &py_name_order))
+		goto error;
+
+	if (!PyDict_Check(entries)) {
+		PyErr_SetString(PyExc_TypeError, "Argument not a dictionary");
+		goto error;
+	}
+
+	name_order = PyObject_IsTrue(py_name_order);
+	if (name_order == -1)
+		goto error;
+	cmp = name_order ? cmp_tree_item_name_order : cmp_tree_item;
+
+	num_entries = PyDict_Size(entries);
+	if (PyErr_Occurred())
+		goto error;
+	qsort_entries = PyMem_New(struct tree_item, num_entries);
+	if (!qsort_entries) {
+		PyErr_NoMemory();
+		goto error;
+	}
+
+	while (PyDict_Next(entries, &pos, &key, &value)) {
+		if (!PyString_Check(key)) {
+			PyErr_SetString(PyExc_TypeError, "Name is not a string");
+			goto error;
+		}
+
+		if (PyTuple_Size(value) != 2) {
+			PyErr_SetString(PyExc_ValueError, "Tuple has invalid size");
+			goto error;
+		}
+
+		py_mode = PyTuple_GET_ITEM(value, 0);
+		if (!PyInt_Check(py_mode)) {
+			PyErr_SetString(PyExc_TypeError, "Mode is not an integral type");
+			goto error;
+		}
+
+		py_sha = PyTuple_GET_ITEM(value, 1);
+		if (!PyString_Check(py_sha)) {
+			PyErr_SetString(PyExc_TypeError, "SHA is not a string");
+			goto error;
+		}
+		qsort_entries[n].name = PyString_AS_STRING(key);
+		qsort_entries[n].mode = PyInt_AS_LONG(py_mode);
+
+		qsort_entries[n].tuple = PyObject_CallFunctionObjArgs(
+		                tree_entry_cls, key, py_mode, py_sha, NULL);
+		if (qsort_entries[n].tuple == NULL)
+			goto error;
+		n++;
+	}
+
+	qsort(qsort_entries, num_entries, sizeof(struct tree_item), cmp);
+
+	ret = PyList_New(num_entries);
+	if (ret == NULL) {
+		PyErr_NoMemory();
+		goto error;
+	}
+
+	for (i = 0; i < num_entries; i++) {
+		PyList_SET_ITEM(ret, i, qsort_entries[i].tuple);
+	}
+	PyMem_Free(qsort_entries);
+	return ret;
+
+error:
+	for (i = 0; i < n; i++) {
+		Py_XDECREF(qsort_entries[i].tuple);
+	}
+	PyMem_Free(qsort_entries);
+	return NULL;
 }
 
 static PyMethodDef py_objects_methods[] = {
-	{ "parse_tree", (PyCFunction)py_parse_tree, METH_VARARGS, NULL },
+	{ "parse_tree", (PyCFunction)py_parse_tree, METH_VARARGS | METH_KEYWORDS,
+	  NULL },
+	{ "sorted_tree_items", py_sorted_tree_items, METH_VARARGS, NULL },
 	{ NULL, NULL, 0, NULL }
 };
 
-void init_objects(void)
+PyMODINIT_FUNC
+init_objects(void)
 {
-	PyObject *m;
+	PyObject *m, *objects_mod, *errors_mod;
 
 	m = Py_InitModule3("_objects", py_objects_methods, NULL);
 	if (m == NULL)
 		return;
+
+
+	errors_mod = PyImport_ImportModule("dulwich.errors");
+	if (errors_mod == NULL)
+		return;
+
+	object_format_exception_cls = PyObject_GetAttrString(
+		errors_mod, "ObjectFormatException");
+	Py_DECREF(errors_mod);
+	if (object_format_exception_cls == NULL)
+		return;
+
+	/* This is a circular import but should be safe since this module is
+	 * imported at at the very bottom of objects.py. */
+	objects_mod = PyImport_ImportModule("dulwich.objects");
+	if (objects_mod == NULL)
+		return;
+
+	tree_entry_cls = PyObject_GetAttrString(objects_mod, "TreeEntry");
+	Py_DECREF(objects_mod);
+	if (tree_entry_cls == NULL)
+		return;
 }

=== modified file 'dulwich/_pack.c'
--- dulwich/_pack.c	2009-05-30 23:30:11 +0000
+++ dulwich/_pack.c	2010-03-31 21:05:52 +0000
@@ -47,6 +47,29 @@
 	return size;
 }
 
+static PyObject *py_chunked_as_string(PyObject *py_buf)
+{
+	if (PyList_Check(py_buf)) {
+		PyObject *sep = PyString_FromString("");
+		if (sep == NULL) {
+			PyErr_NoMemory();
+			return NULL;
+		}
+		py_buf = _PyString_Join(sep, py_buf);
+		Py_DECREF(sep);
+		if (py_buf == NULL) {
+			PyErr_NoMemory();
+			return NULL;
+		}
+	} else if (PyString_Check(py_buf)) {
+		Py_INCREF(py_buf);
+	} else {
+		PyErr_SetString(PyExc_TypeError,
+			"src_buf is not a string or a list of chunks");
+		return NULL;
+	}
+    return py_buf;
+}
 
 static PyObject *py_apply_delta(PyObject *self, PyObject *args)
 {
@@ -56,23 +79,42 @@
 	size_t outindex = 0;
 	int index;
 	uint8_t *out;
-	PyObject *ret;
+	PyObject *ret, *py_src_buf, *py_delta;
 
-	if (!PyArg_ParseTuple(args, "s#s#", (uint8_t *)&src_buf, &src_buf_len, 
-						  (uint8_t *)&delta, &delta_len))
+	if (!PyArg_ParseTuple(args, "OO", &py_src_buf, &py_delta))
 		return NULL;
 
+    py_src_buf = py_chunked_as_string(py_src_buf);
+    if (py_src_buf == NULL)
+        return NULL;
+
+    py_delta = py_chunked_as_string(py_delta);
+    if (py_delta == NULL) {
+        Py_DECREF(py_src_buf);
+        return NULL;
+    }
+
+	src_buf = (uint8_t *)PyString_AS_STRING(py_src_buf);
+	src_buf_len = PyString_GET_SIZE(py_src_buf);
+
+    delta = (uint8_t *)PyString_AS_STRING(py_delta);
+    delta_len = PyString_GET_SIZE(py_delta);
+
     index = 0;
     src_size = get_delta_header_size(delta, &index, delta_len);
     if (src_size != src_buf_len) {
 		PyErr_Format(PyExc_ValueError, 
 			"Unexpected source buffer size: %lu vs %d", src_size, src_buf_len);
+		Py_DECREF(py_src_buf);
+		Py_DECREF(py_delta);
 		return NULL;
 	}
     dest_size = get_delta_header_size(delta, &index, delta_len);
 	ret = PyString_FromStringAndSize(NULL, dest_size);
 	if (ret == NULL) {
 		PyErr_NoMemory();
+		Py_DECREF(py_src_buf);
+		Py_DECREF(py_delta);
 		return NULL;
 	}
 	out = (uint8_t *)PyString_AsString(ret);
@@ -110,21 +152,28 @@
             index += cmd;
 		} else {
 			PyErr_SetString(PyExc_ValueError, "Invalid opcode 0");
+			Py_DECREF(ret);
+            Py_DECREF(py_delta);
+			Py_DECREF(py_src_buf);
 			return NULL;
 		}
 	}
+	Py_DECREF(py_src_buf);
+    Py_DECREF(py_delta);
     
     if (index != delta_len) {
 		PyErr_SetString(PyExc_ValueError, "delta not empty");
+		Py_DECREF(ret);
 		return NULL;
 	}
 
 	if (dest_size != outindex) {
         PyErr_SetString(PyExc_ValueError, "dest size incorrect");
+		Py_DECREF(ret);
 		return NULL;
 	}
 
-    return ret;
+    return Py_BuildValue("[N]", ret);
 }
 
 static PyObject *py_bisect_find_sha(PyObject *self, PyObject *args)

=== modified file 'dulwich/client.py'
--- dulwich/client.py	2009-10-18 14:55:07 +0000
+++ dulwich/client.py	2011-01-05 11:30:32 +0000
@@ -21,17 +21,19 @@
 
 __docformat__ = 'restructuredText'
 
-import os
 import select
 import socket
 import subprocess
+import urlparse
 
 from dulwich.errors import (
-    ChecksumMismatch,
+    SendPackError,
+    UpdateRefsError,
     )
 from dulwich.protocol import (
     Protocol,
     TCP_GIT_PORT,
+    ZERO_SHA,
     extract_capabilities,
     )
 from dulwich.pack import (
@@ -43,85 +45,145 @@
     """Check if a file descriptor is readable."""
     return len(select.select([fileno], [], [], 0)[0]) > 0
 
-
-CAPABILITIES = ["multi_ack", "side-band-64k", "ofs-delta"]
-
-
+COMMON_CAPABILITIES = ['ofs-delta']
+FETCH_CAPABILITIES = ['multi_ack', 'side-band-64k'] + COMMON_CAPABILITIES
+SEND_CAPABILITIES = ['report-status'] + COMMON_CAPABILITIES
+
+# TODO(durin42): this doesn't correctly degrade if the server doesn't
+# support some capabilities. This should work properly with servers
+# that don't support side-band-64k and multi_ack.
 class GitClient(object):
     """Git smart server client.
 
     """
 
-    def __init__(self, can_read, read, write, thin_packs=True, 
-        report_activity=None):
+    def __init__(self, thin_packs=True, report_activity=None):
         """Create a new GitClient instance.
 
-        :param can_read: Function that returns True if there is data available
-            to be read.
-        :param read: Callback for reading data, takes number of bytes to read
-        :param write: Callback for writing data
         :param thin_packs: Whether or not thin packs should be retrieved
         :param report_activity: Optional callback for reporting transport
             activity.
         """
-        self.proto = Protocol(read, write, report_activity)
-        self._can_read = can_read
-        self._capabilities = list(CAPABILITIES)
+        self._report_activity = report_activity
+        self._fetch_capabilities = list(FETCH_CAPABILITIES)
+        self._send_capabilities = list(SEND_CAPABILITIES)
         if thin_packs:
-            self._capabilities.append("thin-pack")
-
-    def capabilities(self):
-        return " ".join(self._capabilities)
-
-    def read_refs(self):
+            self._fetch_capabilities.append('thin-pack')
+
+    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 = {}
         # Receive refs from server
-        for pkt in self.proto.read_pkt_seq():
-            (sha, ref) = pkt.rstrip("\n").split(" ", 1)
+        for pkt in proto.read_pkt_seq():
+            (sha, ref) = pkt.rstrip('\n').split(' ', 1)
             if server_capabilities is None:
                 (ref, server_capabilities) = extract_capabilities(ref)
             refs[ref] = sha
         return refs, server_capabilities
 
+    def _parse_status_report(self, proto):
+        unpack = proto.read_pkt_line().strip()
+        if unpack != 'unpack ok':
+            st = True
+            # flush remaining error data
+            while st is not None:
+                st = proto.read_pkt_line()
+            raise SendPackError(unpack)
+        statuses = []
+        errs = False
+        ref_status = proto.read_pkt_line()
+        while ref_status:
+            ref_status = ref_status.strip()
+            statuses.append(ref_status)
+            if not ref_status.startswith('ok '):
+                errs = True
+            ref_status = proto.read_pkt_line()
+
+        if errs:
+            ref_status = {}
+            ok = set()
+            for status in statuses:
+                if ' ' not in status:
+                    # malformed response, move on to the next one
+                    continue
+                status, ref = status.split(' ', 1)
+
+                if status == 'ng':
+                    if ' ' in ref:
+                        ref, status = ref.split(' ', 1)
+                else:
+                    ok.add(ref)
+                ref_status[ref] = status
+            raise UpdateRefsError('%s failed to update' %
+                                  ', '.join([ref for ref in ref_status
+                                             if ref not in ok]),
+                                  ref_status=ref_status)
+
+
+    # TODO(durin42): add side-band-64k capability support here and advertise it
     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 the shas of the 
+        :param generate_pack_contents: Function that can return 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
         """
-        old_refs, server_capabilities = self.read_refs()
+        proto, unused_can_read = self._connect('receive-pack', path)
+        old_refs, server_capabilities = self.read_refs(proto)
+        if 'report-status' not in server_capabilities:
+            self._send_capabilities.remove('report-status')
         new_refs = determine_wants(old_refs)
         if not new_refs:
-            self.proto.write_pkt_line(None)
+            proto.write_pkt_line(None)
             return {}
         want = []
-        have = [x for x in old_refs.values() if not x == "0" * 40]
+        have = [x for x in old_refs.values() if not x == ZERO_SHA]
         sent_capabilities = False
         for refname in set(new_refs.keys() + old_refs.keys()):
-            old_sha1 = old_refs.get(refname, "0" * 40)
-            new_sha1 = new_refs.get(refname, "0" * 40)
+            old_sha1 = old_refs.get(refname, ZERO_SHA)
+            new_sha1 = new_refs.get(refname, ZERO_SHA)
             if old_sha1 != new_sha1:
                 if sent_capabilities:
-                    self.proto.write_pkt_line("%s %s %s" % (old_sha1, new_sha1, refname))
+                    proto.write_pkt_line('%s %s %s' % (old_sha1, new_sha1,
+                                                            refname))
                 else:
-                    self.proto.write_pkt_line("%s %s %s\0%s" % (old_sha1, new_sha1, refname, self.capabilities()))
+                    proto.write_pkt_line(
+                      '%s %s %s\0%s' % (old_sha1, new_sha1, refname,
+                                        ' '.join(self._send_capabilities)))
                     sent_capabilities = True
-            if not new_sha1 in (have, "0" * 40):
+            if new_sha1 not in have and new_sha1 != ZERO_SHA:
                 want.append(new_sha1)
-        self.proto.write_pkt_line(None)
+        proto.write_pkt_line(None)
         if not want:
             return new_refs
         objects = generate_pack_contents(have, want)
-        (entries, sha) = write_pack_data(self.proto.write_file(), objects, 
-                                         len(objects))
-        
-        # read the final confirmation sha
-        client_sha = self.proto.read(20)
-        if not client_sha in (None, "", sha):
-            raise ChecksumMismatch(sha, client_sha)
-            
+        entries, sha = write_pack_data(proto.write_file(), objects,
+                                       len(objects))
+
+        if 'report-status' in self._send_capabilities:
+            self._parse_status_report(proto)
+        # wait for EOF before returning
+        data = proto.read()
+        if data:
+            raise SendPackError('Unexpected response %r' % data)
         return new_refs
 
     def fetch(self, path, target, determine_wants=None, progress=None):
@@ -129,7 +191,7 @@
 
         :param path: Path to fetch from
         :param target: Target repository to fetch into
-        :param determine_wants: Optional function to determine what refs 
+        :param determine_wants: Optional function to determine what refs
             to fetch
         :param progress: Optional progress function
         :return: remote refs
@@ -138,8 +200,8 @@
             determine_wants = target.object_store.determine_wants_all
         f, commit = target.object_store.add_pack()
         try:
-            return self.fetch_pack(path, determine_wants, target.graph_walker, 
-                                   f.write, progress)
+            return self.fetch_pack(path, determine_wants,
+                target.get_graph_walker(), f.write, progress)
         finally:
             commit()
 
@@ -152,44 +214,49 @@
         :param pack_data: Callback called for each bit of data in the pack
         :param progress: Callback for progress reports (strings)
         """
-        (refs, server_capabilities) = self.read_refs()
+        proto, can_read = self._connect('upload-pack', path)
+        (refs, server_capabilities) = self.read_refs(proto)
         wants = determine_wants(refs)
         if not wants:
-            self.proto.write_pkt_line(None)
+            proto.write_pkt_line(None)
             return refs
         assert isinstance(wants, list) and type(wants[0]) == str
-        self.proto.write_pkt_line("want %s %s\n" % (wants[0], self.capabilities()))
+        proto.write_pkt_line('want %s %s\n' % (
+            wants[0], ' '.join(self._fetch_capabilities)))
         for want in wants[1:]:
-            self.proto.write_pkt_line("want %s\n" % want)
-        self.proto.write_pkt_line(None)
+            proto.write_pkt_line('want %s\n' % want)
+        proto.write_pkt_line(None)
         have = graph_walker.next()
         while have:
-            self.proto.write_pkt_line("have %s\n" % have)
-            if self._can_read():
-                pkt = self.proto.read_pkt_line()
-                parts = pkt.rstrip("\n").split(" ")
-                if parts[0] == "ACK":
+            proto.write_pkt_line('have %s\n' % have)
+            if can_read():
+                pkt = proto.read_pkt_line()
+                parts = pkt.rstrip('\n').split(' ')
+                if parts[0] == 'ACK':
                     graph_walker.ack(parts[1])
-                    assert parts[2] == "continue"
+                    assert parts[2] == 'continue'
             have = graph_walker.next()
-        self.proto.write_pkt_line("done\n")
-        pkt = self.proto.read_pkt_line()
+        proto.write_pkt_line('done\n')
+        pkt = proto.read_pkt_line()
         while pkt:
-            parts = pkt.rstrip("\n").split(" ")
-            if parts[0] == "ACK":
-                graph_walker.ack(pkt.split(" ")[1])
-            if len(parts) < 3 or parts[2] != "continue":
+            parts = pkt.rstrip('\n').split(' ')
+            if parts[0] == 'ACK':
+                graph_walker.ack(pkt.split(' ')[1])
+            if len(parts) < 3 or parts[2] != 'continue':
                 break
-            pkt = self.proto.read_pkt_line()
-        for pkt in self.proto.read_pkt_seq():
+            pkt = proto.read_pkt_line()
+        # TODO(durin42): this is broken if the server didn't support the
+        # side-band-64k capability.
+        for pkt in proto.read_pkt_seq():
             channel = ord(pkt[0])
             pkt = pkt[1:]
             if channel == 1:
                 pack_data(pkt)
             elif channel == 2:
-                progress(pkt)
+                if progress is not None:
+                    progress(pkt)
             else:
-                raise AssertionError("Invalid sideband channel %d" % channel)
+                raise AssertionError('Invalid sideband channel %d' % channel)
         return refs
 
 
@@ -197,96 +264,35 @@
     """A Git Client that works over TCP directly (i.e. git://)."""
 
     def __init__(self, host, port=None, *args, **kwargs):
-        self._socket = socket.socket(type=socket.SOCK_STREAM)
         if port is None:
             port = TCP_GIT_PORT
-        self._socket.connect((host, port))
-        self.rfile = self._socket.makefile('rb', -1)
-        self.wfile = self._socket.makefile('wb', 0)
-        self.host = host
-        super(TCPGitClient, self).__init__(lambda: _fileno_can_read(self._socket.fileno()), self.rfile.read, self.wfile.write, *args, **kwargs)
-
-    def send_pack(self, path, changed_refs, generate_pack_contents):
-        """Send a pack to a remote host.
-
-        :param path: Path of the repository on the remote host
-        """
-        self.proto.send_cmd("git-receive-pack", path, "host=%s" % self.host)
-        return super(TCPGitClient, self).send_pack(path, changed_refs, generate_pack_contents)
-
-    def fetch_pack(self, path, determine_wants, graph_walker, pack_data, progress):
-        """Fetch a pack from the remote host.
-        
-        :param path: Path of the reposiutory on the remote host
-        :param determine_wants: Callback that receives available refs dict and 
-            should return list of sha's to fetch.
-        :param graph_walker: GraphWalker instance used to find missing shas
-        :param pack_data: Callback for writing pack data
-        :param progress: Callback for writing progress
-        """
-        self.proto.send_cmd("git-upload-pack", path, "host=%s" % self.host)
-        return super(TCPGitClient, self).fetch_pack(path, determine_wants,
-            graph_walker, pack_data, progress)
-
-
-class SubprocessGitClient(GitClient):
-    """Git client that talks to a server using a subprocess."""
-
-    def __init__(self, *args, **kwargs):
-        self.proc = None
-        self._args = args
-        self._kwargs = kwargs
-
-    def _connect(self, service, *args, **kwargs):
-        argv = [service] + list(args)
-        self.proc = subprocess.Popen(argv, bufsize=0,
-                                stdin=subprocess.PIPE,
-                                stdout=subprocess.PIPE)
-        def read_fn(size):
-            return self.proc.stdout.read(size)
-        def write_fn(data):
-            self.proc.stdin.write(data)
-            self.proc.stdin.flush()
-        return GitClient(lambda: _fileno_can_read(self.proc.stdout.fileno()), read_fn, write_fn, *args, **kwargs)
-
-    def send_pack(self, path, changed_refs, generate_pack_contents):
-        """Upload a pack to the server.
-
-        :param path: Path to the git repository on the server
-        :param changed_refs: Dictionary with new values for the refs
-        :param generate_pack_contents: Function that returns an iterator over 
-            objects to send
-        """
-        client = self._connect("git-receive-pack", path)
-        return client.send_pack(path, changed_refs, generate_pack_contents)
-
-    def fetch_pack(self, path, determine_wants, graph_walker, pack_data, 
-        progress):
-        """Retrieve a pack from the server
-
-        :param path: Path to the git repository on the server
-        :param determine_wants: Function that receives existing refs 
-            on the server and returns a list of desired shas
-        :param graph_walker: GraphWalker instance
-        :param pack_data: Function that can write pack data
-        :param progress: Function that can write progress texts
-        """
-        client = self._connect("git-upload-pack", path)
-        return client.fetch_pack(path, determine_wants, graph_walker, pack_data,
-                                 progress)
-
-
-class SSHSubprocess(object):
-    """A socket-like object that talks to an ssh subprocess via pipes."""
+        self._host = host
+        self._port = port
+        GitClient.__init__(self, *args, **kwargs)
+
+    def _connect(self, cmd, path):
+        s = socket.socket(type=socket.SOCK_STREAM)
+        s.connect((self._host, self._port))
+        # -1 means system default buffering
+        rfile = s.makefile('rb', -1)
+        # 0 means unbuffered
+        wfile = s.makefile('wb', 0)
+        proto = Protocol(rfile.read, wfile.write,
+                         report_activity=self._report_activity)
+        proto.send_cmd('git-%s' % cmd, path, 'host=%s' % self._host)
+        return proto, lambda: _fileno_can_read(s)
+
+
+class SubprocessWrapper(object):
+    """A socket-like object that talks to a subprocess via pipes."""
 
     def __init__(self, proc):
         self.proc = proc
-
-    def send(self, data):
-        return os.write(self.proc.stdin.fileno(), data)
-
-    def recv(self, count):
-        return self.proc.stdout.read(count)
+        self.read = proc.stdout.read
+        self.write = proc.stdin.write
+
+    def can_read(self):
+        return _fileno_can_read(self.proc.stdout.fileno())
 
     def close(self):
         self.proc.stdin.close()
@@ -294,6 +300,21 @@
         self.proc.wait()
 
 
+class SubprocessGitClient(GitClient):
+    """Git client that talks to a server using a subprocess."""
+
+    def __init__(self, *args, **kwargs):
+        self._connection = None
+        GitClient.__init__(self, *args, **kwargs)
+
+    def _connect(self, service, path):
+        argv = ['git', service, path]
+        p = SubprocessWrapper(
+            subprocess.Popen(argv, bufsize=0, stdin=subprocess.PIPE,
+                             stdout=subprocess.PIPE))
+        return Protocol(p.read, p.write,
+                        report_activity=self._report_activity), p.can_read
+
 class SSHVendor(object):
 
     def connect_ssh(self, host, command, username=None, port=None):
@@ -302,12 +323,12 @@
         if port is not None:
             args.extend(['-p', str(port)])
         if username is not None:
-            host = "%s@%s" % (username, host)
+            host = '%s@%s' % (username, host)
         args.append(host)
         proc = subprocess.Popen(args + command,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE)
-        return SSHSubprocess(proc)
+        return SubprocessWrapper(proc)
 
 # Can be overridden by users
 get_ssh_vendor = SSHVendor
@@ -319,18 +340,42 @@
         self.host = host
         self.port = port
         self.username = username
-        self._args = args
-        self._kwargs = kwargs
-
-    def send_pack(self, path, determine_wants, generate_pack_contents):
-        remote = get_ssh_vendor().connect_ssh(self.host, ["git-receive-pack '%s'" % path], port=self.port, username=self.username)
-        client = GitClient(lambda: _fileno_can_read(remote.proc.stdout.fileno()), remote.recv, remote.send, *self._args, **self._kwargs)
-        return client.send_pack(path, determine_wants, generate_pack_contents)
-
-    def fetch_pack(self, path, determine_wants, graph_walker, pack_data,
-        progress):
-        remote = get_ssh_vendor().connect_ssh(self.host, ["git-upload-pack '%s'" % path], port=self.port, username=self.username)
-        client = GitClient(lambda: _fileno_can_read(remote.proc.stdout.fileno()), remote.recv, remote.send, *self._args, **self._kwargs)
-        return client.fetch_pack(path, determine_wants, graph_walker, pack_data,
-                                 progress)
-
+        GitClient.__init__(self, *args, **kwargs)
+        self.alternative_paths = {}
+
+    def _get_cmd_path(self, cmd):
+        return self.alternative_paths.get(cmd, 'git-%s' % cmd)
+
+    def _connect(self, cmd, path):
+        con = get_ssh_vendor().connect_ssh(
+            self.host, ["%s '%s'" % (self._get_cmd_path(cmd), path)],
+            port=self.port, username=self.username)
+        return Protocol(con.read, con.write), con.can_read
+
+
+def get_transport_and_path(uri):
+    """Obtain a git client from a URI or path.
+
+    :param uri: URI or path
+    :return: Tuple with client instance and relative path.
+    """
+    parsed = urlparse.urlparse(uri)
+    if parsed.scheme == 'git':
+        return TCPGitClient(parsed.hostname, port=parsed.port), parsed.path
+    elif parsed.scheme == 'git+ssh':
+        return SSHGitClient(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.
+        return SSHGitClient(parsed.scheme), parsed.path
+    elif parsed.scheme:
+        raise ValueError('Unknown git protocol scheme: %s' % parsed.scheme)
+    elif '@' in parsed.path and ':' in parsed.path:
+        # SSH with user@host:foo.
+        user_host, path = parsed.path.split(':')
+        user, host = user_host.rsplit('@')
+        return SSHGitClient(host, username=user), path
+
+    # Otherwise, assume it's a local path.
+    return SubprocessGitClient(), uri

=== added file 'dulwich/diff_tree.py'
--- dulwich/diff_tree.py	1970-01-01 00:00:00 +0000
+++ dulwich/diff_tree.py	2010-12-19 18:11:43 +0000
@@ -0,0 +1,495 @@
+# diff_tree.py -- Utilities for diffing files and trees.
+# Copyright (C) 2010 Google, Inc.
+#
+# 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; either version 2
+# or (at your option) a 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.
+
+"""Utilities for diffing files and trees."""
+
+from cStringIO import StringIO
+import itertools
+import stat
+
+from dulwich._compat import (
+    defaultdict,
+    TreeChangeTuple,
+    )
+from dulwich.objects import (
+    S_ISGITLINK,
+    TreeEntry,
+    )
+
+# TreeChange type constants.
+CHANGE_ADD = 'add'
+CHANGE_MODIFY = 'modify'
+CHANGE_DELETE = 'delete'
+CHANGE_RENAME = 'rename'
+CHANGE_COPY = 'copy'
+CHANGE_UNCHANGED = 'unchanged'
+
+_NULL_ENTRY = TreeEntry(None, None, None)
+
+_MAX_SCORE = 100
+_RENAME_THRESHOLD = 60
+_MAX_FILES = 200
+_REWRITE_THRESHOLD = None
+
+
+class TreeChange(TreeChangeTuple):
+    """Class encapsulating a single change between two trees."""
+
+    @classmethod
+    def add(cls, new):
+        return cls(CHANGE_ADD, _NULL_ENTRY, new)
+
+    @classmethod
+    def delete(cls, old):
+        return cls(CHANGE_DELETE, old, _NULL_ENTRY)
+
+
+def _tree_entries(path, tree):
+    result = []
+    if not tree:
+        return result
+    for entry in tree.iteritems(name_order=True):
+        result.append(entry.in_path(path))
+    return result
+
+
+def _merge_entries(path, tree1, tree2):
+    """Merge the entries of two trees.
+
+    :param path: A path to prepend to all tree entry names.
+    :param tree1: The first Tree object to iterate, or None.
+    :param tree2: The second Tree object to iterate, or None.
+    :return: A list of pairs of TreeEntry objects for each pair of entries in
+        the trees. If an entry exists in one tree but not the other, the other
+        entry will have all attributes set to None. If neither entry's path is
+        None, they are guaranteed to match.
+    """
+    entries1 = _tree_entries(path, tree1)
+    entries2 = _tree_entries(path, tree2)
+    i1 = i2 = 0
+    len1 = len(entries1)
+    len2 = len(entries2)
+
+    result = []
+    while i1 < len1 and i2 < len2:
+        entry1 = entries1[i1]
+        entry2 = entries2[i2]
+        if entry1.path < entry2.path:
+            result.append((entry1, _NULL_ENTRY))
+            i1 += 1
+        elif entry1.path > entry2.path:
+            result.append((_NULL_ENTRY, entry2))
+            i2 += 1
+        else:
+            result.append((entry1, entry2))
+            i1 += 1
+            i2 += 1
+    for i in xrange(i1, len1):
+        result.append((entries1[i], _NULL_ENTRY))
+    for i in xrange(i2, len2):
+        result.append((_NULL_ENTRY, entries2[i]))
+    return result
+
+
+def _is_tree(entry):
+    mode = entry.mode
+    if mode is None:
+        return False
+    return stat.S_ISDIR(mode)
+
+
+def walk_trees(store, tree1_id, tree2_id, prune_identical=False):
+    """Recursively walk all the entries of two trees.
+
+    Iteration is depth-first pre-order, as in e.g. os.walk.
+
+    :param store: An ObjectStore for looking up objects.
+    :param tree1_id: The SHA of the first Tree object to iterate, or None.
+    :param tree2_id: The SHA of the second Tree object to iterate, or None.
+    :param prune_identical: If True, identical subtrees will not be walked.
+    :return: Iterator over Pairs of TreeEntry objects for each pair of entries
+        in the trees and their subtrees recursively. If an entry exists in one
+        tree but not the other, the other entry will have all attributes set
+        to None. If neither entry's path is None, they are guaranteed to
+        match.
+    """
+    # This could be fairly easily generalized to >2 trees if we find a use case.
+    mode1 = tree1_id and stat.S_IFDIR or None
+    mode2 = tree2_id and stat.S_IFDIR or None
+    todo = [(TreeEntry('', mode1, tree1_id), TreeEntry('', mode2, tree2_id))]
+    while todo:
+        entry1, entry2 = todo.pop()
+        is_tree1 = _is_tree(entry1)
+        is_tree2 = _is_tree(entry2)
+        if prune_identical and is_tree1 and is_tree2 and entry1 == entry2:
+            continue
+
+        tree1 = is_tree1 and store[entry1.sha] or None
+        tree2 = is_tree2 and store[entry2.sha] or None
+        path = entry1.path or entry2.path
+        todo.extend(reversed(_merge_entries(path, tree1, tree2)))
+        yield entry1, entry2
+
+
+def _skip_tree(entry):
+    if entry.mode is None or stat.S_ISDIR(entry.mode):
+        return _NULL_ENTRY
+    return entry
+
+
+def tree_changes(store, tree1_id, tree2_id, want_unchanged=False):
+    """Find the differences between the contents of two trees.
+
+    :param store: An ObjectStore for looking up objects.
+    :param tree1_id: The SHA of the source tree.
+    :param tree2_id: The SHA of the target tree.
+    :param want_unchanged: If True, include TreeChanges for unmodified entries
+        as well.
+    :return: Iterator over TreeChange instances for each change between the
+        source and target tree.
+    """
+    entries = walk_trees(store, tree1_id, tree2_id,
+                         prune_identical=(not want_unchanged))
+    for entry1, entry2 in entries:
+        if entry1 == entry2 and not want_unchanged:
+            continue
+
+        # Treat entries for trees as missing.
+        entry1 = _skip_tree(entry1)
+        entry2 = _skip_tree(entry2)
+
+        if entry1 != _NULL_ENTRY and entry2 != _NULL_ENTRY:
+            if stat.S_IFMT(entry1.mode) != stat.S_IFMT(entry2.mode):
+                # File type changed: report as delete/add.
+                yield TreeChange.delete(entry1)
+                entry1 = _NULL_ENTRY
+                change_type = CHANGE_ADD
+            elif entry1 == entry2:
+                change_type = CHANGE_UNCHANGED
+            else:
+                change_type = CHANGE_MODIFY
+        elif entry1 != _NULL_ENTRY:
+            change_type = CHANGE_DELETE
+        elif entry2 != _NULL_ENTRY:
+            change_type = CHANGE_ADD
+        else:
+            # Both were None because at least one was a tree.
+            continue
+        yield TreeChange(change_type, entry1, entry2)
+
+
+_BLOCK_SIZE = 64
+
+
+def _count_blocks(obj):
+    """Count the blocks in an object.
+
+    Splits the data into blocks either on lines or <=64-byte chunks of lines.
+
+    :param obj: The object to count blocks for.
+    :return: A dict of block hashcode -> total bytes occurring.
+    """
+    block_counts = defaultdict(int)
+    block = StringIO()
+    n = 0
+
+    # Cache attrs as locals to avoid expensive lookups in the inner loop.
+    block_write = block.write
+    block_seek = block.seek
+    block_truncate = block.truncate
+    block_getvalue = block.getvalue
+
+    for c in itertools.chain(*obj.as_raw_chunks()):
+        block_write(c)
+        n += 1
+        if c == '\n' or n == _BLOCK_SIZE:
+            value = block_getvalue()
+            block_counts[hash(value)] += len(value)
+            block_seek(0)
+            block_truncate()
+            n = 0
+    if n > 0:
+        last_block = block_getvalue()
+        block_counts[hash(last_block)] += len(last_block)
+    return block_counts
+
+
+def _common_bytes(blocks1, blocks2):
+    """Count the number of common bytes in two block count dicts.
+
+    :param block1: The first dict of block hashcode -> total bytes.
+    :param block2: The second dict of block hashcode -> total bytes.
+    :return: The number of bytes in common between blocks1 and blocks2. This is
+        only approximate due to possible hash collisions.
+    """
+    # Iterate over the smaller of the two dicts, since this is symmetrical.
+    if len(blocks1) > len(blocks2):
+        blocks1, blocks2 = blocks2, blocks1
+    score = 0
+    for block, count1 in blocks1.iteritems():
+        count2 = blocks2.get(block)
+        if count2:
+            score += min(count1, count2)
+    return score
+
+
+def _similarity_score(obj1, obj2, block_cache=None):
+    """Compute a similarity score for two objects.
+
+    :param obj1: The first object to score.
+    :param obj2: The second object to score.
+    :param block_cache: An optional dict of SHA to block counts to cache results
+        between calls.
+    :return: The similarity score between the two objects, defined as the number
+        of bytes in common between the two objects divided by the maximum size,
+        scaled to the range 0-100.
+    """
+    if block_cache is None:
+        block_cache = {}
+    if obj1.id not in block_cache:
+        block_cache[obj1.id] = _count_blocks(obj1)
+    if obj2.id not in block_cache:
+        block_cache[obj2.id] = _count_blocks(obj2)
+
+    common_bytes = _common_bytes(block_cache[obj1.id], block_cache[obj2.id])
+    max_size = max(obj1.raw_length(), obj2.raw_length())
+    if not max_size:
+        return _MAX_SCORE
+    return int(float(common_bytes) * _MAX_SCORE / max_size)
+
+
+def _tree_change_key(entry):
+    # Sort by old path then new path. If only one exists, use it for both keys.
+    path1 = entry.old.path
+    path2 = entry.new.path
+    if path1 is None:
+        path1 = path2
+    if path2 is None:
+        path2 = path1
+    return (path1, path2)
+
+
+class RenameDetector(object):
+    """Object for handling rename detection between two trees."""
+
+    def __init__(self, store, tree1_id, tree2_id,
+                 rename_threshold=_RENAME_THRESHOLD, max_files=_MAX_FILES,
+                 rewrite_threshold=_REWRITE_THRESHOLD,
+                 find_copies_harder=False):
+        """Initialize the rename detector.
+
+        :param store: An ObjectStore for looking up objects.
+        :param tree1_id: The SHA of the first Tree.
+        :param tree2_id: The SHA of the second Tree.
+        :param rename_threshold: The threshold similarity score for considering
+            an add/delete pair to be a rename/copy; see _similarity_score.
+        :param max_files: The maximum number of adds and deletes to consider, or
+            None for no limit. The detector is guaranteed to compare no more
+            than max_files ** 2 add/delete pairs. This limit is provided because
+            rename detection can be quadratic in the project size. If the limit
+            is exceeded, no content rename detection is attempted.
+        :param rewrite_threshold: The threshold similarity score below which a
+            modify should be considered a delete/add, or None to not break
+            modifies; see _similarity_score.
+        :param find_copies_harder: If True, consider unmodified files when
+            detecting copies.
+        """
+        self._tree1_id = tree1_id
+        self._tree2_id = tree2_id
+        self._store = store
+        self._rename_threshold = rename_threshold
+        self._rewrite_threshold = rewrite_threshold
+        self._max_files = max_files
+        self._find_copies_harder = find_copies_harder
+
+        self._adds = []
+        self._deletes = []
+        self._changes = []
+
+    def _should_split(self, change):
+        if (self._rewrite_threshold is None or change.type != CHANGE_MODIFY or
+            change.old.sha == change.new.sha):
+            return False
+        old_obj = self._store[change.old.sha]
+        new_obj = self._store[change.new.sha]
+        return _similarity_score(old_obj, new_obj) < self._rewrite_threshold
+
+    def _collect_changes(self):
+        for change in tree_changes(self._store, self._tree1_id, self._tree2_id,
+                                   want_unchanged=self._find_copies_harder):
+            if change.type == CHANGE_ADD:
+                self._adds.append(change)
+            elif change.type == CHANGE_DELETE:
+                self._deletes.append(change)
+            elif self._should_split(change):
+                self._deletes.append(TreeChange.delete(change.old))
+                self._adds.append(TreeChange.add(change.new))
+            elif (self._find_copies_harder and (
+              change.type == CHANGE_MODIFY or change.type == CHANGE_UNCHANGED)):
+                # Treat modified/unchanged as deleted rather than splitting it,
+                # to avoid spurious renames.
+                self._deletes.append(change)
+            else:
+                self._changes.append(change)
+
+    def _prune(self, add_paths, delete_paths):
+        self._adds = [a for a in self._adds if a.new.path not in add_paths]
+        self._deletes = [d for d in self._deletes
+                         if d.old.path not in delete_paths]
+
+    def _find_exact_renames(self):
+        add_map = defaultdict(list)
+        for add in self._adds:
+            add_map[add.new.sha].append(add.new)
+        delete_map = defaultdict(list)
+        for delete in self._deletes:
+            # Keep track of whether the delete was actually marked as a delete.
+            # If not, it must have been added due to find_copies_harder, and
+            # needs to be marked as a copy.
+            is_delete = delete.type == CHANGE_DELETE
+            delete_map[delete.old.sha].append((delete.old, is_delete))
+
+        add_paths = set()
+        delete_paths = set()
+        for sha, sha_deletes in delete_map.iteritems():
+            sha_adds = add_map[sha]
+            for (old, is_delete), new in itertools.izip(sha_deletes, sha_adds):
+                if stat.S_IFMT(old.mode) != stat.S_IFMT(new.mode):
+                    continue
+                delete_paths.add(old.path)
+                add_paths.add(new.path)
+                new_type = is_delete and CHANGE_RENAME or CHANGE_COPY
+                self._changes.append(TreeChange(new_type, old, new))
+
+            num_extra_adds = len(sha_adds) - len(sha_deletes)
+            # TODO(dborowitz): Less arbitrary way of dealing with extra copies.
+            old = sha_deletes[0][0]
+            if num_extra_adds:
+                for new in sha_adds[-num_extra_adds:]:
+                    add_paths.add(new.path)
+                    self._changes.append(TreeChange(CHANGE_COPY, old, new))
+        self._prune(add_paths, delete_paths)
+
+    def _find_content_renames(self):
+        # TODO: Optimizations:
+        #  - Compare object sizes before counting blocks.
+        #  - Skip if delete's S_IFMT differs from all adds.
+        #  - Skip if adds or deletes is empty.
+        # Match C git's behavior of not attempting to find content renames if
+        # the matrix size exceeds the threshold.
+        if len(self._adds) * len(self._deletes) > self._max_files ** 2:
+            return
+
+        check_paths = self._rename_threshold is not None
+        candidates = []
+        for delete in self._deletes:
+            if S_ISGITLINK(delete.old.mode):
+                continue  # Git links don't exist in this repo.
+            old_sha = delete.old.sha
+            old_obj = self._store[old_sha]
+            old_blocks = _count_blocks(old_obj)
+            for add in self._adds:
+                if stat.S_IFMT(delete.old.mode) != stat.S_IFMT(add.new.mode):
+                    continue
+                new_obj = self._store[add.new.sha]
+                score = _similarity_score(old_obj, new_obj,
+                                          block_cache={old_sha: old_blocks})
+                if score > self._rename_threshold:
+                    if check_paths and delete.old.path == add.new.path:
+                        # If the paths match, this must be a split modify, so
+                        # make sure it comes out as a modify.
+                        new_type = CHANGE_MODIFY
+                    elif delete.type != CHANGE_DELETE:
+                        # If it's in deletes but not marked as a delete, it must
+                        # have been added due to find_copies_harder, and needs
+                        # to be marked as a copy.
+                        new_type = CHANGE_COPY
+                    else:
+                        new_type = CHANGE_RENAME
+                    rename = TreeChange(new_type, delete.old, add.new)
+                    candidates.append((-score, rename))
+
+        # Sort scores from highest to lowest, but keep names in ascending order.
+        candidates.sort()
+
+        delete_paths = set()
+        add_paths = set()
+        for _, change in candidates:
+            new_path = change.new.path
+            if new_path in add_paths:
+                continue
+            old_path = change.old.path
+            orig_type = change.type
+            if old_path in delete_paths:
+                change = TreeChange(CHANGE_COPY, change.old, change.new)
+
+            # If the candidate was originally a copy, that means it came from a
+            # modified or unchanged path, so we don't want to prune it.
+            if orig_type != CHANGE_COPY:
+                delete_paths.add(old_path)
+            add_paths.add(new_path)
+            self._changes.append(change)
+        self._prune(add_paths, delete_paths)
+
+    def _join_modifies(self):
+        if self._rewrite_threshold is None:
+            return
+
+        modifies = {}
+        delete_map = dict((d.old.path, d) for d in self._deletes)
+        for add in self._adds:
+            path = add.new.path
+            delete = delete_map.get(path)
+            if (delete is not None and
+              stat.S_IFMT(delete.old.mode) == stat.S_IFMT(add.new.mode)):
+                modifies[path] = TreeChange(CHANGE_MODIFY, delete.old, add.new)
+
+        self._adds = [a for a in self._adds if a.new.path not in modifies]
+        self._deletes = [a for a in self._deletes if a.new.path not in modifies]
+        self._changes += modifies.values()
+
+    def _sorted_changes(self):
+        result = []
+        result.extend(self._adds)
+        result.extend(self._deletes)
+        result.extend(self._changes)
+        result.sort(key=_tree_change_key)
+        return result
+
+    def _prune_unchanged(self):
+        self._deletes = [d for d in self._deletes if d.type != CHANGE_UNCHANGED]
+
+    def changes_with_renames(self):
+        """Iterate TreeChanges between the two trees, with rename detection."""
+        self._collect_changes()
+        self._find_exact_renames()
+        self._find_content_renames()
+        self._join_modifies()
+        self._prune_unchanged()
+        return self._sorted_changes()
+
+
+# Hold on to the pure-python implementations for testing.
+_is_tree_py = _is_tree
+_merge_entries_py = _merge_entries
+_count_blocks_py = _count_blocks
+try:
+    # Try to import C versions
+    from dulwich._diff_tree import _is_tree, _merge_entries, _count_blocks
+except ImportError:
+    pass

=== modified file 'dulwich/errors.py'
--- dulwich/errors.py	2009-09-08 12:45:38 +0000
+++ dulwich/errors.py	2010-12-21 23:15:57 +0000
@@ -1,17 +1,17 @@
 # errors.py -- errors for dulwich
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
 # Copyright (C) 2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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
 # 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,
@@ -19,71 +19,83 @@
 
 """Dulwich-related exception classes and utility functions."""
 
+import binascii
+
+
 class ChecksumMismatch(Exception):
     """A checksum didn't match the expected contents."""
 
     def __init__(self, expected, got, extra=None):
+        if len(expected) == 20:
+            expected = binascii.hexlify(expected)
+        if len(got) == 20:
+            got = binascii.hexlify(got)
         self.expected = expected
         self.got = got
         self.extra = extra
         if self.extra is None:
-            Exception.__init__(self, 
+            Exception.__init__(self,
                 "Checksum mismatch: Expected %s, got %s" % (expected, got))
         else:
             Exception.__init__(self,
-                "Checksum mismatch: Expected %s, got %s; %s" % 
+                "Checksum mismatch: Expected %s, got %s; %s" %
                 (expected, got, extra))
 
 
 class WrongObjectException(Exception):
     """Baseclass for all the _ is not a _ exceptions on objects.
-  
+
     Do not instantiate directly.
-  
-    Subclasses should define a _type attribute that indicates what
+
+    Subclasses should define a type_name attribute that indicates what
     was expected if they were raised.
     """
-  
+
     def __init__(self, sha, *args, **kwargs):
-        string = "%s is not a %s" % (sha, self._type)
-        Exception.__init__(self, string)
+        Exception.__init__(self, "%s is not a %s" % (sha, self.type_name))
 
 
 class NotCommitError(WrongObjectException):
     """Indicates that the sha requested does not point to a commit."""
-  
-    _type = 'commit'
+
+    type_name = 'commit'
 
 
 class NotTreeError(WrongObjectException):
     """Indicates that the sha requested does not point to a tree."""
-  
-    _type = 'tree'
+
+    type_name = 'tree'
+
+
+class NotTagError(WrongObjectException):
+    """Indicates that the sha requested does not point to a tag."""
+
+    type_name = 'tag'
 
 
 class NotBlobError(WrongObjectException):
     """Indicates that the sha requested does not point to a blob."""
-  
-    _type = 'blob'
+
+    type_name = 'blob'
 
 
 class MissingCommitError(Exception):
     """Indicates that a commit was not found in the repository"""
-  
+
     def __init__(self, sha, *args, **kwargs):
         Exception.__init__(self, "%s is not in the revision store" % sha)
 
 
 class ObjectMissing(Exception):
     """Indicates that a requested object is missing."""
-  
+
     def __init__(self, sha, *args, **kwargs):
         Exception.__init__(self, "%s is not in the pack" % sha)
 
 
 class ApplyDeltaError(Exception):
     """Indicates that applying a delta failed."""
-    
+
     def __init__(self, *args, **kwargs):
         Exception.__init__(self, *args, **kwargs)
 
@@ -97,8 +109,23 @@
 
 class GitProtocolError(Exception):
     """Git protocol exception."""
-    
-    def __init__(self, *args, **kwargs):
+
+    def __init__(self, *args, **kwargs):
+        Exception.__init__(self, *args, **kwargs)
+
+
+class SendPackError(GitProtocolError):
+    """An error occurred during send_pack."""
+
+    def __init__(self, *args, **kwargs):
+        Exception.__init__(self, *args, **kwargs)
+
+
+class UpdateRefsError(GitProtocolError):
+    """The server reported errors updating refs."""
+
+    def __init__(self, *args, **kwargs):
+        self.ref_status = kwargs.pop('ref_status')
         Exception.__init__(self, *args, **kwargs)
 
 
@@ -108,3 +135,38 @@
     def __init__(self):
         Exception.__init__(self,
             "The remote server unexpectedly closed the connection.")
+
+
+class UnexpectedCommandError(GitProtocolError):
+    """Unexpected command received in a proto line."""
+
+    def __init__(self, command):
+        if command is None:
+            command = 'flush-pkt'
+        else:
+            command = 'command %s' % command
+        GitProtocolError.__init__(self, 'Protocol got unexpected %s' % command)
+
+
+class FileFormatException(Exception):
+    """Base class for exceptions relating to reading git file formats."""
+
+
+class PackedRefsException(FileFormatException):
+    """Indicates an error parsing a packed-refs file."""
+
+
+class ObjectFormatException(FileFormatException):
+    """Indicates an error parsing an object."""
+
+
+class NoIndexPresent(Exception):
+    """No index is present."""
+
+
+class CommitError(Exception):
+    """An error occurred while performing a commit."""
+
+
+class RefFormatError(Exception):
+    """Indicates an invalid ref name."""

=== added file 'dulwich/fastexport.py'
--- dulwich/fastexport.py	1970-01-01 00:00:00 +0000
+++ dulwich/fastexport.py	2010-12-12 05:15:03 +0000
@@ -0,0 +1,220 @@
+# __init__.py -- Fast export/import functionality
+# Copyright (C) 2010 Jelmer Vernooij <jelmer@xxxxxxxxx>
+#
+# 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.index import (
+    commit_tree,
+    )
+from dulwich.objects import (
+    Blob,
+    Commit,
+    Tag,
+    )
+from fastimport import (
+    commands,
+    errors as fastimport_errors,
+    parser,
+    processor,
+    )
+
+import stat
+
+
+def split_email(text):
+    (name, email) = text.rsplit(" <", 1)
+    return (name, email.rstrip(">"))
+
+
+class GitFastExporter(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 print_cmd(self, cmd):
+        self.outf.write("%r\n" % cmd)
+
+    def _allocate_marker(self):
+        self._marker_idx+=1
+        return str(self._marker_idx)
+
+    def _export_blob(self, blob):
+        marker = self._allocate_marker()
+        self.markers[marker] = blob.id
+        return (commands.BlobCommand(marker, blob.data), marker)
+
+    def emit_blob(self, blob):
+        (cmd, marker) = self._export_blob(blob)
+        self.print_cmd(cmd)
+        return marker
+
+    def _iter_files(self, base_tree, new_tree):
+        for (old_path, new_path), (old_mode, new_mode), (old_hexsha, new_hexsha) in \
+                self.store.tree_changes(base_tree, new_tree):
+            if new_path is None:
+                yield commands.FileDeleteCommand(old_path)
+                continue
+            if not stat.S_ISDIR(new_mode):
+                blob = self.store[new_hexsha]
+                marker = self.emit_blob(blob)
+            if old_path != new_path and old_path is not None:
+                yield commands.FileRenameCommand(old_path, new_path)
+            if old_mode != new_mode or old_hexsha != new_hexsha:
+                yield commands.FileModifyCommand(new_path, new_mode, marker, None)
+
+    def _export_commit(self, commit, ref, base_tree=None):
+        file_cmds = list(self._iter_files(base_tree, commit.tree))
+        marker = self._allocate_marker()
+        if commit.parents:
+            from_ = commit.parents[0]
+            merges = commit.parents[1:]
+        else:
+            from_ = None
+            merges = []
+        author, author_email = split_email(commit.author)
+        committer, committer_email = split_email(commit.committer)
+        cmd = commands.CommitCommand(ref, marker,
+            (author, author_email, commit.author_time, commit.author_timezone),
+            (committer, committer_email, commit.commit_time, commit.commit_timezone),
+            commit.message, from_, merges, file_cmds)
+        return (cmd, marker)
+
+    def emit_commit(self, commit, ref, base_tree=None):
+        cmd, marker = self._export_commit(commit, ref, base_tree)
+        self.print_cmd(cmd)
+        return marker
+
+
+class GitImportProcessor(processor.ImportProcessor):
+    """An import processor that imports into a Git repository using Dulwich.
+
+    """
+    # FIXME: Batch creation of objects?
+
+    def __init__(self, repo, params=None, verbose=False, outf=None):
+        processor.ImportProcessor.__init__(self, params, verbose)
+        self.repo = repo
+        self.last_commit = None
+        self.markers = {}
+        self._contents = {}
+
+    def import_stream(self, stream):
+        p = parser.ImportParser(stream)
+        self.process(p.iter_commands)
+        return self.markers
+
+    def blob_handler(self, cmd):
+        """Process a BlobCommand."""
+        blob = Blob.from_string(cmd.data)
+        self.repo.object_store.add_object(blob)
+        if cmd.mark:
+            self.markers[cmd.mark] = blob.id
+
+    def checkpoint_handler(self, cmd):
+        """Process a CheckpointCommand."""
+        pass
+
+    def commit_handler(self, cmd):
+        """Process a CommitCommand."""
+        commit = Commit()
+        if cmd.author is not None:
+            author = cmd.author
+        else:
+            author = cmd.committer
+        (author_name, author_email, author_timestamp, author_timezone) = author
+        (committer_name, committer_email, commit_timestamp, commit_timezone) = cmd.committer
+        commit.author = "%s <%s>" % (author_name, author_email)
+        commit.author_timezone = author_timezone
+        commit.author_time = int(author_timestamp)
+        commit.committer = "%s <%s>" % (committer_name, committer_email)
+        commit.commit_timezone = commit_timezone
+        commit.commit_time = int(commit_timestamp)
+        commit.message = cmd.message
+        commit.parents = []
+        if cmd.from_:
+            self._reset_base(cmd.from_)
+        for filecmd in cmd.iter_files():
+            if filecmd.name == "filemodify":
+                if filecmd.data is not None:
+                    blob = Blob.from_string(filecmd.data)
+                    self.repo.object_store.add(blob)
+                    blob_id = blob.id
+                else:
+                    assert filecmd.dataref[0] == ":", "non-marker refs not supported yet"
+                    blob_id = self.markers[filecmd.dataref[1:]]
+                self._contents[filecmd.path] = (filecmd.mode, blob_id)
+            elif filecmd.name == "filedelete":
+                del self._contents[filecmd.path]
+            elif filecmd.name == "filecopy":
+                self._contents[filecmd.dest_path] = self._contents[filecmd.src_path]
+            elif filecmd.name == "filerename":
+                self._contents[filecmd.new_path] = self._contents[filecmd.old_path]
+                del self._contents[filecmd.old_path]
+            elif filecmd.name == "filedeleteall":
+                self._contents = {}
+            else:
+                raise Exception("Command %s not supported" % filecmd.name)
+        commit.tree = commit_tree(self.repo.object_store,
+            ((path, hexsha, mode) for (path, (mode, hexsha)) in
+                self._contents.iteritems()))
+        if self.last_commit is not None:
+            commit.parents.append(self.last_commit)
+        commit.parents += cmd.merges
+        self.repo.object_store.add_object(commit)
+        self.repo[cmd.ref] = commit.id
+        self.last_commit = commit.id
+        if cmd.mark:
+            self.markers[cmd.mark] = commit.id
+
+    def progress_handler(self, cmd):
+        """Process a ProgressCommand."""
+        pass
+
+    def _reset_base(self, commit_id):
+        if self.last_commit == commit_id:
+            return
+        self.last_commit = commit_id
+        self._contents = {}
+        tree_id = self.repo[commit_id].tree
+        for (path, mode, hexsha) in (
+                self.repo.object_store.iter_tree_contents(tree_id)):
+            self._contents[path] = (mode, hexsha)
+
+    def reset_handler(self, cmd):
+        """Process a ResetCommand."""
+        self._reset_base(cmd.from_)
+        self.rep.refs[cmd.from_] = cmd.id
+
+    def tag_handler(self, cmd):
+        """Process a TagCommand."""
+        tag = Tag()
+        tag.tagger = cmd.tagger
+        tag.message = cmd.message
+        tag.name = cmd.tag
+        self.repo.add_object(tag)
+        self.repo.refs["refs/tags/" + tag.name] = tag.id
+
+    def feature_handler(self, cmd):
+        """Process a FeatureCommand."""
+        raise fastimport_errors.UnknownFeature(cmd.feature_name)

=== added file 'dulwich/file.py'
--- dulwich/file.py	1970-01-01 00:00:00 +0000
+++ dulwich/file.py	2010-11-26 15:39:40 +0000
@@ -0,0 +1,161 @@
+# file.py -- Safe access to git files
+# Copyright (C) 2010 Google, Inc.
+#
+# 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) a 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.
+
+"""Safe access to git files."""
+
+import errno
+import os
+import tempfile
+
+def ensure_dir_exists(dirname):
+    """Ensure a directory exists, creating if necessary."""
+    try:
+        os.makedirs(dirname)
+    except OSError, e:
+        if e.errno != errno.EEXIST:
+            raise
+
+
+def fancy_rename(oldname, newname):
+    """Rename file with temporary backup file to rollback if rename fails"""
+    if not os.path.exists(newname):
+        try:
+            os.rename(oldname, newname)
+        except OSError, e:
+            raise
+        return
+
+    # destination file exists
+    try:
+        (fd, tmpfile) = tempfile.mkstemp(".tmp", prefix=oldname+".", dir=".")
+        os.close(fd)
+        os.remove(tmpfile)
+    except OSError, e:
+        # either file could not be created (e.g. permission problem)
+        # or could not be deleted (e.g. rude virus scanner)
+        raise
+    try:
+        os.rename(newname, tmpfile)
+    except OSError, e:
+        raise   # no rename occurred
+    try:
+        os.rename(oldname, newname)
+    except OSError, e:
+        os.rename(tmpfile, newname)
+        raise
+    os.remove(tmpfile)
+
+
+def GitFile(filename, mode='rb', bufsize=-1):
+    """Create a file object that obeys the git file locking protocol.
+
+    :return: a builtin file object or a _GitFile object
+
+    :note: See _GitFile for a description of the file locking protocol.
+
+    Only read-only and write-only (binary) modes are supported; r+, w+, and a
+    are not.  To read and write from the same file, you can take advantage of
+    the fact that opening a file for write does not actually open the file you
+    request.
+    """
+    if 'a' in mode:
+        raise IOError('append mode not supported for Git files')
+    if '+' in mode:
+        raise IOError('read/write mode not supported for Git files')
+    if 'b' not in mode:
+        raise IOError('text mode not supported for Git files')
+    if 'w' in mode:
+        return _GitFile(filename, mode, bufsize)
+    else:
+        return file(filename, mode, bufsize)
+
+
+class _GitFile(object):
+    """File that follows the git locking protocol for writes.
+
+    All writes to a file foo will be written into foo.lock in the same
+    directory, and the lockfile will be renamed to overwrite the original file
+    on close.
+
+    :note: You *must* call close() or abort() on a _GitFile for the lock to be
+        released. Typically this will happen in a finally block.
+    """
+
+    PROXY_PROPERTIES = set(['closed', 'encoding', 'errors', 'mode', 'name',
+                            'newlines', 'softspace'])
+    PROXY_METHODS = ('__iter__', 'flush', 'fileno', 'isatty', 'next', 'read',
+                     'readline', 'readlines', 'xreadlines', 'seek', 'tell',
+                     'truncate', 'write', 'writelines')
+    def __init__(self, filename, mode, bufsize):
+        self._filename = filename
+        self._lockfilename = '%s.lock' % self._filename
+        fd = os.open(self._lockfilename,
+            os.O_RDWR | os.O_CREAT | os.O_EXCL | getattr(os, "O_BINARY", 0))
+        self._file = os.fdopen(fd, mode, bufsize)
+        self._closed = False
+
+        for method in self.PROXY_METHODS:
+            setattr(self, method, getattr(self._file, method))
+
+    def abort(self):
+        """Close and discard the lockfile without overwriting the target.
+
+        If the file is already closed, this is a no-op.
+        """
+        if self._closed:
+            return
+        self._file.close()
+        try:
+            os.remove(self._lockfilename)
+            self._closed = True
+        except OSError, e:
+            # The file may have been removed already, which is ok.
+            if e.errno != errno.ENOENT:
+                raise
+            self._closed = True
+
+    def close(self):
+        """Close this file, saving the lockfile over the original.
+
+        :note: If this method fails, it will attempt to delete the lockfile.
+            However, it is not guaranteed to do so (e.g. if a filesystem becomes
+            suddenly read-only), which will prevent future writes to this file
+            until the lockfile is removed manually.
+        :raises OSError: if the original file could not be overwritten. The lock
+            file is still closed, so further attempts to write to the same file
+            object will raise ValueError.
+        """
+        if self._closed:
+            return
+        self._file.close()
+        try:
+            try:
+                os.rename(self._lockfilename, self._filename)
+            except OSError, e:
+                # Windows versions prior to Vista don't support atomic renames
+                if e.errno != errno.EEXIST:
+                    raise
+                fancy_rename(self._lockfilename, self._filename)
+        finally:
+            self.abort()
+
+    def __getattr__(self, name):
+        """Proxy property calls to the underlying file."""
+        if name in self.PROXY_PROPERTIES:
+            return getattr(self._file, name)
+        raise AttributeError(name)

=== modified file 'dulwich/index.py'
--- dulwich/index.py	2009-10-18 17:24:17 +0000
+++ dulwich/index.py	2010-05-24 17:21:02 +0000
@@ -1,16 +1,16 @@
-# index.py -- File parser/write for the git index file
+# index.py -- File parser/writer for the git index file
 # Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
- 
+#
 # 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 opinion) 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,
@@ -22,6 +22,7 @@
 import stat
 import struct
 
+from dulwich.file import GitFile
 from dulwich.objects import (
     S_IFGITLINK,
     S_ISGITLINK,
@@ -35,6 +36,27 @@
     )
 
 
+def pathsplit(path):
+    """Split a /-delimited path into a directory part and a basename.
+
+    :param path: The path to split.
+    :return: Tuple with directory name and basename
+    """
+    try:
+        (dirname, basename) = path.rsplit("/", 1)
+    except ValueError:
+        return ("", path)
+    else:
+        return (dirname, basename)
+
+
+def pathjoin(*args):
+    """Join a /-delimited path.
+
+    """
+    return "/".join([p for p in args if p])
+
+
 def read_cache_time(f):
     """Read a cache time.
     
@@ -173,7 +195,7 @@
 
     def write(self):
         """Write current contents of index to disk."""
-        f = open(self._filename, 'wb')
+        f = GitFile(self._filename, 'wb')
         try:
             f = SHA1Writer(f)
             write_index_dict(f, self._byname)
@@ -182,7 +204,9 @@
 
     def read(self):
         """Read current contents of index from disk."""
-        f = open(self._filename, 'rb')
+        if not os.path.exists(self._filename):
+            return
+        f = GitFile(self._filename, 'rb')
         try:
             f = SHA1Reader(f)
             for x in read_index(f):
@@ -232,6 +256,10 @@
         # Remove the old entry if any
         self._byname[name] = x
 
+    def __delitem__(self, name):
+        assert isinstance(name, str)
+        del self._byname[name]
+
     def iteritems(self):
         return self._byname.iteritems()
 
@@ -261,6 +289,14 @@
         for name in mine:
             yield ((None, name), (None, self.get_mode(name)), (None, self.get_sha1(name)))
 
+    def commit(self, object_store):
+        """Create a new tree from an index.
+
+        :param object_store: Object store to save the tree in
+        :return: Root tree SHA
+        """
+        return commit_tree(object_store, self.iterblobs())
+
 
 def commit_tree(object_store, blobs):
     """Commit a new tree.
@@ -273,7 +309,7 @@
     def add_tree(path):
         if path in trees:
             return trees[path]
-        dirname, basename = os.path.split(path)
+        dirname, basename = pathsplit(path)
         t = add_tree(dirname)
         assert isinstance(basename, str)
         newtree = {}
@@ -282,7 +318,7 @@
         return newtree
 
     for path, sha, mode in blobs:
-        tree_path, basename = os.path.split(path)
+        tree_path, basename = pathsplit(path)
         tree = add_tree(tree_path)
         tree[basename] = (mode, sha)
 
@@ -291,7 +327,7 @@
         for basename, entry in trees[path].iteritems():
             if type(entry) == dict:
                 mode = stat.S_IFDIR
-                sha = build_tree(os.path.join(path, basename))
+                sha = build_tree(pathjoin(path, basename))
             else:
                 (mode, sha) = entry
             tree.add(mode, basename, sha)
@@ -305,5 +341,7 @@
 
     :param object_store: Object store to save the tree in
     :param index: Index file
+    :note: This function is deprecated, use index.commit() instead.
+    :return: Root tree sha.
     """
     return commit_tree(object_store, index.iterblobs())

=== added file 'dulwich/log_utils.py'
--- dulwich/log_utils.py	1970-01-01 00:00:00 +0000
+++ dulwich/log_utils.py	2010-06-15 16:53:17 +0000
@@ -0,0 +1,67 @@
+# log_utils.py -- Logging utilities for Dulwich
+# Copyright (C) 2010 Google, Inc.
+#
+# 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; either version 2
+# of the License, or (at your option) any later version.
+#
+# 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.
+
+"""Logging utilities for Dulwich.
+
+Any module that uses logging needs to do compile-time initialization to set up
+the logging environment. Since Dulwich is also used as a library, clients may
+not want to see any logging output. In that case, we need to use a special
+handler to suppress spurious warnings like "No handlers could be found for
+logger dulwich.foo".
+
+For details on the _NullHandler approach, see:
+http://docs.python.org/library/logging.html#configuring-logging-for-a-library
+
+For many modules, the only function from the logging module they need is
+getLogger; this module exports that function for convenience. If a calling
+module needs something else, it can import the standard logging module directly.
+"""
+
+import logging
+import sys
+
+getLogger = logging.getLogger
+
+
+class _NullHandler(logging.Handler):
+    """No-op logging handler to avoid unexpected logging warnings."""
+
+    def emit(self, record):
+        pass
+
+
+_NULL_HANDLER = _NullHandler()
+_DULWICH_LOGGER = getLogger('dulwich')
+_DULWICH_LOGGER.addHandler(_NULL_HANDLER)
+
+
+def default_logging_config():
+    """Set up the default Dulwich loggers."""
+    remove_null_handler()
+    logging.basicConfig(level=logging.INFO, stream=sys.stderr,
+                        format='%(asctime)s %(levelname)s: %(message)s')
+
+
+def remove_null_handler():
+    """Remove the null handler from the Dulwich loggers.
+
+    If a caller wants to set up logging using something other than
+    default_logging_config, calling this function first is a minor optimization
+    to avoid the overhead of using the _NullHandler.
+    """
+    _DULWICH_LOGGER.removeHandler(_NULL_HANDLER)

=== modified file 'dulwich/lru_cache.py'
--- dulwich/lru_cache.py	2009-05-05 19:37:14 +0000
+++ dulwich/lru_cache.py	2010-05-24 17:21:02 +0000
@@ -1,3 +1,4 @@
+# lru_cache.py -- Simple LRU cache for dulwich
 # Copyright (C) 2006, 2008 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify

=== removed file 'dulwich/misc.py'
--- dulwich/misc.py	2009-03-09 17:54:18 +0000
+++ dulwich/misc.py	1970-01-01 00:00:00 +0000
@@ -1,90 +0,0 @@
-# misc.py -- For dealing with python2.4 oddness
-# Copyright (C) 2008 Canonical Ltd.
-# 
-# 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) a later version.
-# 
-# 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.
-"""Misc utilities to work with python2.4.
-
-These utilities can all be deleted when dulwich decides it wants to stop
-support for python 2.4.
-"""
-try:
-    import hashlib
-except ImportError:
-    import sha
-import struct
-
-
-class defaultdict(dict):
-    """A python 2.4 equivalent of collections.defaultdict."""
-
-    def __init__(self, default_factory=None, *a, **kw):
-        if (default_factory is not None and
-            not hasattr(default_factory, '__call__')):
-            raise TypeError('first argument must be callable')
-        dict.__init__(self, *a, **kw)
-        self.default_factory = default_factory
-
-    def __getitem__(self, key):
-        try:
-            return dict.__getitem__(self, key)
-        except KeyError:
-            return self.__missing__(key)
-
-    def __missing__(self, key):
-        if self.default_factory is None:
-            raise KeyError(key)
-        self[key] = value = self.default_factory()
-        return value
-
-    def __reduce__(self):
-        if self.default_factory is None:
-            args = tuple()
-        else:
-            args = self.default_factory,
-        return type(self), args, None, None, self.items()
-
-    def copy(self):
-        return self.__copy__()
-
-    def __copy__(self):
-        return type(self)(self.default_factory, self)
-
-    def __deepcopy__(self, memo):
-        import copy
-        return type(self)(self.default_factory,
-                          copy.deepcopy(self.items()))
-    def __repr__(self):
-        return 'defaultdict(%s, %s)' % (self.default_factory,
-                                        dict.__repr__(self))
-
-
-def make_sha(source=''):
-    """A python2.4 workaround for the sha/hashlib module fiasco."""
-    try:
-        return hashlib.sha1(source)
-    except NameError:
-        sha1 = sha.sha(source)
-        return sha1
-
-
-def unpack_from(fmt, buf, offset=0):
-    """A python2.4 workaround for struct missing unpack_from."""
-    try:
-        return struct.unpack_from(fmt, buf, offset)
-    except AttributeError:
-        b = buf[offset:offset+struct.calcsize(fmt)]
-        return struct.unpack(fmt, b)
-

=== modified file 'dulwich/object_store.py'
--- dulwich/object_store.py	2009-10-07 13:44:53 +0000
+++ dulwich/object_store.py	2011-01-05 11:44:45 +0000
@@ -1,16 +1,16 @@
-# object_store.py -- Object store for git objects 
+# object_store.py -- Object store for git objects
 # Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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; either version 2
 # or (at your option) a 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,
@@ -20,15 +20,21 @@
 """Git object store interfaces and implementation."""
 
 
+import errno
 import itertools
 import os
 import stat
 import tempfile
 import urllib2
 
+from dulwich.diff_tree import (
+    tree_changes,
+    walk_trees,
+    )
 from dulwich.errors import (
     NotTreeError,
     )
+from dulwich.file import GitFile
 from dulwich.objects import (
     Commit,
     ShaFile,
@@ -36,18 +42,22 @@
     Tree,
     hex_to_sha,
     sha_to_hex,
+    hex_to_filename,
     S_ISGITLINK,
+    object_class,
     )
 from dulwich.pack import (
     Pack,
-    PackData, 
-    iter_sha1, 
+    PackData,
+    ThinPackData,
+    iter_sha1,
     load_pack_index,
     write_pack,
     write_pack_data,
     write_pack_index_v2,
     )
 
+INFODIR = 'info'
 PACKDIR = 'pack'
 
 
@@ -55,7 +65,8 @@
     """Object store interface."""
 
     def determine_wants_all(self, refs):
-	    return [sha for (ref, sha) in refs.iteritems() if not sha in self and not ref.endswith("^{}")]
+        return [sha for (ref, sha) in refs.iteritems()
+                if not sha in self and not ref.endswith("^{}")]
 
     def iter_shas(self, shas):
         """Iterate over the objects for the specified shas.
@@ -65,22 +76,38 @@
         """
         return ObjectStoreIterator(self, shas)
 
+    def contains_loose(self, sha):
+        """Check if a particular object is present by SHA1 and is loose."""
+        raise NotImplementedError(self.contains_loose)
+
+    def contains_packed(self, sha):
+        """Check if a particular object is present by SHA1 and is packed."""
+        raise NotImplementedError(self.contains_packed)
+
     def __contains__(self, sha):
-        """Check if a particular object is present by SHA1."""
-        raise NotImplementedError(self.__contains__)
+        """Check if a particular object is present by SHA1.
+
+        This method makes no distinction between loose and packed objects.
+        """
+        return self.contains_packed(sha) or self.contains_loose(sha)
+
+    @property
+    def packs(self):
+        """Iterable of pack objects."""
+        raise NotImplementedError
 
     def get_raw(self, name):
         """Obtain the raw text for an object.
-        
+
         :param name: sha for the object.
-        :return: tuple with object type and object contents.
+        :return: tuple with numeric type and object contents.
         """
         raise NotImplementedError(self.get_raw)
 
     def __getitem__(self, sha):
         """Obtain an object by SHA1."""
-        type, uncomp = self.get_raw(sha)
-        return ShaFile.from_raw_string(type, uncomp)
+        type_num, uncomp = self.get_raw(sha)
+        return ShaFile.from_raw_string(type_num, uncomp)
 
     def __iter__(self):
         """Iterate over the SHAs that are present in this store."""
@@ -105,88 +132,43 @@
         :param object_store: Object store to use for retrieving tree contents
         :param tree: SHA1 of the root tree
         :param want_unchanged: Whether unchanged files should be reported
-        :return: Iterator over tuples with (oldpath, newpath), (oldmode, newmode), (oldsha, newsha)
-        """
-        todo = set([(source, target, "")])
-        while todo:
-            (sid, tid, path) = todo.pop()
-            if sid is not None:
-                stree = self[sid]
-            else:
-                stree = {}
-            if tid is not None:
-                ttree = self[tid]
-            else:
-                ttree = {}
-            for name, oldmode, oldhexsha in stree.iteritems():
-                if path == "":
-                    oldchildpath = name
-                else:
-                    oldchildpath = "%s/%s" % (path, name)
-                try:
-                    (newmode, newhexsha) = ttree[name]
-                    newchildpath = oldchildpath
-                except KeyError:
-                    newmode = None
-                    newhexsha = None
-                    newchildpath = None
-                if (want_unchanged or oldmode != newmode or 
-                    oldhexsha != newhexsha):
-                    if stat.S_ISDIR(oldmode):
-                        if newmode is None or stat.S_ISDIR(newmode):
-                            todo.add((oldhexsha, newhexsha, oldchildpath))
-                        else:
-                            # entry became a file
-                            todo.add((oldhexsha, None, oldchildpath))
-                            yield ((None, newchildpath), (None, newmode), (None, newhexsha))
-                    else:
-                        if newmode is not None and stat.S_ISDIR(newmode):
-                            # entry became a dir
-                            yield ((oldchildpath, None), (oldmode, None), (oldhexsha, None))
-                            todo.add((None, newhexsha, newchildpath))
-                        else:
-                            yield ((oldchildpath, newchildpath), (oldmode, newmode), (oldhexsha, newhexsha))
-
-            for name, newmode, newhexsha in ttree.iteritems():
-                if path == "":
-                    childpath = name
-                else:
-                    childpath = "%s/%s" % (path, name)
-                if not name in stree:
-                    if not stat.S_ISDIR(newmode):
-                        yield ((None, childpath), (None, newmode), (None, newhexsha))
-                    else:
-                        todo.add((None, newhexsha, childpath))
-
-    def iter_tree_contents(self, tree):
-        """Yield (path, mode, hexsha) tuples for all non-Tree objects in a tree.
-
-        :param tree: SHA1 of the root of the tree
-        """
-        todo = set([(tree, "")])
-        while todo:
-            (tid, tpath) = todo.pop()
-            tree = self[tid]
-            for name, mode, hexsha in tree.iteritems(): 
-                if tpath == "":
-                    path = name
-                else:
-                    path = "%s/%s" % (tpath, name)
-                if stat.S_ISDIR(mode):
-                    todo.add((hexsha, path))
-                else:
-                    yield path, mode, hexsha
-
-    def find_missing_objects(self, haves, wants, progress=None):
+        :return: Iterator over tuples with
+            (oldpath, newpath), (oldmode, newmode), (oldsha, newsha)
+        """
+        for change in tree_changes(self, source, target,
+                                   want_unchanged=want_unchanged):
+            yield ((change.old.path, change.new.path),
+                   (change.old.mode, change.new.mode),
+                   (change.old.sha, change.new.sha))
+
+    def iter_tree_contents(self, tree_id, include_trees=False):
+        """Iterate the contents of a tree and all subtrees.
+
+        Iteration is depth-first pre-order, as in e.g. os.walk.
+
+        :param tree_id: SHA1 of the tree.
+        :param include_trees: If True, include tree objects in the iteration.
+        :return: Iterator over TreeEntry namedtuples for all the objects in a
+            tree.
+        """
+        for entry, _ in walk_trees(self, tree_id, None):
+            if not stat.S_ISDIR(entry.mode) or include_trees:
+                yield entry
+
+    def find_missing_objects(self, haves, wants, progress=None,
+                             get_tagged=None):
         """Find the missing objects required for a set of revisions.
 
         :param haves: Iterable over SHAs already in common.
         :param wants: Iterable over SHAs of objects to fetch.
-        :param progress: Simple progress function that will be called with 
+        :param progress: Simple progress function that will be called with
             updated progress strings.
+        :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+            sha for including tags.
         :return: Iterator over (sha, path) pairs.
         """
-        return iter(MissingObjectFinder(self, haves, wants, progress).next, None)
+        finder = MissingObjectFinder(self, haves, wants, progress, get_tagged)
+        return iter(finder.next, None)
 
     def find_common_revisions(self, graphwalker):
         """Find which revisions this store has in common using graphwalker.
@@ -205,106 +187,107 @@
 
     def get_graph_walker(self, heads):
         """Obtain a graph walker for this object store.
-        
+
         :param heads: Local heads to start search with
         :return: GraphWalker object
         """
         return ObjectStoreGraphWalker(heads, lambda sha: self[sha].parents)
 
-    def generate_pack_contents(self, have, want):
+    def generate_pack_contents(self, have, want, progress=None):
         """Iterate over the contents of a pack file.
 
         :param have: List of SHA1s of objects that should not be sent
         :param want: List of SHA1s of objects that should be sent
-        """
-        return self.iter_shas(self.find_missing_objects(have, want))
-
-
-class DiskObjectStore(BaseObjectStore):
-    """Git-style object store that exists on disk."""
-
-    def __init__(self, path):
-        """Open an object store.
-
-        :param path: Path of the object store.
-        """
-        self.path = path
+        :param progress: Optional progress reporting method
+        """
+        return self.iter_shas(self.find_missing_objects(have, want, progress))
+
+    def peel_sha(self, sha):
+        """Peel all tags from a SHA.
+
+        :param sha: The object SHA to peel.
+        :return: The fully-peeled SHA1 of a tag object, after peeling all
+            intermediate tags; if the original ref does not point to a tag, this
+            will equal the original SHA1.
+        """
+        obj = self[sha]
+        obj_class = object_class(obj.type_name)
+        while obj_class is Tag:
+            obj_class, sha = obj.object
+            obj = self[sha]
+        return obj
+
+
+class PackBasedObjectStore(BaseObjectStore):
+
+    def __init__(self):
         self._pack_cache = None
-        self.pack_dir = os.path.join(self.path, PACKDIR)
 
-    def __contains__(self, sha):
-        """Check if a particular object is present by SHA1."""
+    def contains_packed(self, sha):
+        """Check if a particular object is present by SHA1 and is packed."""
         for pack in self.packs:
             if sha in pack:
                 return True
-        ret = self._get_shafile(sha)
-        if ret is not None:
-            return True
         return False
 
-    def __iter__(self):
-        """Iterate over the SHAs that are present in this store."""
-        iterables = self.packs + [self._iter_shafile_shas()]
-        return itertools.chain(*iterables)
-
-    @property
-    def packs(self):
-        """List with pack objects."""
-        if self._pack_cache is None:
-            self._pack_cache = list(self._load_packs())
-        return self._pack_cache
-
     def _load_packs(self):
-        if not os.path.exists(self.pack_dir):
-            return
-        for name in os.listdir(self.pack_dir):
-            if name.startswith("pack-") and name.endswith(".pack"):
-                yield Pack(os.path.join(self.pack_dir, name[:-len(".pack")]))
-
-    def _add_known_pack(self, path):
+        raise NotImplementedError(self._load_packs)
+
+    def _pack_cache_stale(self):
+        """Check whether the pack cache is stale."""
+        raise NotImplementedError(self._pack_cache_stale)
+
+    def _add_known_pack(self, pack):
         """Add a newly appeared pack to the cache by path.
 
         """
         if self._pack_cache is not None:
-            self._pack_cache.append(Pack(path))
-
-    def _get_shafile_path(self, sha):
-        dir = sha[:2]
-        file = sha[2:]
-        # Check from object dir
-        return os.path.join(self.path, dir, file)
-
-    def _iter_shafile_shas(self):
-        for base in os.listdir(self.path):
-            if len(base) != 2:
-                continue
-            for rest in os.listdir(os.path.join(self.path, base)):
-                yield base+rest
-
-    def _get_shafile(self, sha):
-        path = self._get_shafile_path(sha)
-        if os.path.exists(path):
-          return ShaFile.from_file(path)
-        return None
-
-    def _add_shafile(self, sha, o):
-        dir = os.path.join(self.path, sha[:2])
-        if not os.path.isdir(dir):
-            os.mkdir(dir)
-        path = os.path.join(dir, sha[2:])
-        if os.path.exists(path):
-            return # Already there, no need to write again
-        f = open(path, 'w+')
-        try:
-            f.write(o.as_legacy_object())
-        finally:
-            f.close()
+            self._pack_cache.append(pack)
+
+    @property
+    def packs(self):
+        """List with pack objects."""
+        if self._pack_cache is None or self._pack_cache_stale():
+            self._pack_cache = self._load_packs()
+        return self._pack_cache
+
+    def _iter_loose_objects(self):
+        """Iterate over the SHAs of all loose objects."""
+        raise NotImplementedError(self._iter_loose_objects)
+
+    def _get_loose_object(self, sha):
+        raise NotImplementedError(self._get_loose_object)
+
+    def _remove_loose_object(self, sha):
+        raise NotImplementedError(self._remove_loose_object)
+
+    def pack_loose_objects(self):
+        """Pack loose objects.
+        
+        :return: Number of objects packed
+        """
+        objects = set()
+        for sha in self._iter_loose_objects():
+            objects.add((self._get_loose_object(sha), None))
+        self.add_objects(objects)
+        for obj, path in objects:
+            self._remove_loose_object(obj.id)
+        return len(objects)
+
+    def __iter__(self):
+        """Iterate over the SHAs that are present in this store."""
+        iterables = self.packs + [self._iter_loose_objects()]
+        return itertools.chain(*iterables)
+
+    def contains_loose(self, sha):
+        """Check if a particular object is present by SHA1 and is loose."""
+        return self._get_loose_object(sha) is not None
 
     def get_raw(self, name):
         """Obtain the raw text for an object.
-        
+
         :param name: sha for the object.
-        :return: tuple with object type and object contents.
+        :return: tuple with numeric type and object contents.
         """
         if len(name) == 40:
             sha = hex_to_sha(name)
@@ -313,67 +296,154 @@
             sha = name
             hexsha = None
         else:
-            raise AssertionError
+            raise AssertionError("Invalid object name %r" % name)
         for pack in self.packs:
             try:
                 return pack.get_raw(sha)
             except KeyError:
                 pass
-        if hexsha is None: 
+        if hexsha is None:
             hexsha = sha_to_hex(name)
-        ret = self._get_shafile(hexsha)
+        ret = self._get_loose_object(hexsha)
         if ret is not None:
-            return ret.type, ret.as_raw_string()
+            return ret.type_num, ret.as_raw_string()
         raise KeyError(hexsha)
 
+    def add_objects(self, objects):
+        """Add a set of objects to this object store.
+
+        :param objects: Iterable over objects, should support __len__.
+        :return: Pack object of the objects written.
+        """
+        if len(objects) == 0:
+            # Don't bother writing an empty pack file
+            return
+        f, commit = self.add_pack()
+        write_pack_data(f, objects, len(objects))
+        return commit()
+
+
+class DiskObjectStore(PackBasedObjectStore):
+    """Git-style object store that exists on disk."""
+
+    def __init__(self, path):
+        """Open an object store.
+
+        :param path: Path of the object store.
+        """
+        super(DiskObjectStore, self).__init__()
+        self.path = path
+        self.pack_dir = os.path.join(self.path, PACKDIR)
+        self._pack_cache_time = 0
+
+    def _load_packs(self):
+        pack_files = []
+        try:
+            self._pack_cache_time = os.stat(self.pack_dir).st_mtime
+            pack_dir_contents = os.listdir(self.pack_dir)
+            for name in pack_dir_contents:
+                # TODO: verify that idx exists first
+                if name.startswith("pack-") and name.endswith(".pack"):
+                    filename = os.path.join(self.pack_dir, name)
+                    pack_files.append((os.stat(filename).st_mtime, filename))
+        except OSError, e:
+            if e.errno == errno.ENOENT:
+                return []
+            raise
+        pack_files.sort(reverse=True)
+        suffix_len = len(".pack")
+        return [Pack(f[:-suffix_len]) for _, f in pack_files]
+
+    def _pack_cache_stale(self):
+        try:
+            return os.stat(self.pack_dir).st_mtime > self._pack_cache_time
+        except OSError, e:
+            if e.errno == errno.ENOENT:
+                return True
+            raise
+
+    def _get_shafile_path(self, sha):
+        # Check from object dir
+        return hex_to_filename(self.path, sha)
+
+    def _iter_loose_objects(self):
+        for base in os.listdir(self.path):
+            if len(base) != 2:
+                continue
+            for rest in os.listdir(os.path.join(self.path, base)):
+                yield base+rest
+
+    def _get_loose_object(self, sha):
+        path = self._get_shafile_path(sha)
+        try:
+            return ShaFile.from_path(path)
+        except (OSError, IOError), e:
+            if e.errno == errno.ENOENT:
+                return None
+            raise
+
+    def _remove_loose_object(self, sha):
+        os.remove(self._get_shafile_path(sha))
+
     def move_in_thin_pack(self, path):
         """Move a specific file containing a pack into the pack directory.
 
-        :note: The file should be on the same file system as the 
+        :note: The file should be on the same file system as the
             packs directory.
 
         :param path: Path to the pack file.
         """
-        data = PackData(path)
+        data = ThinPackData(self.get_raw, path)
 
         # Write index for the thin pack (do we really need this?)
-        temppath = os.path.join(self.pack_dir, 
+        temppath = os.path.join(self.pack_dir,
             sha_to_hex(urllib2.randombytes(20))+".tempidx")
-        data.create_index_v2(temppath, self.get_raw)
+        data.create_index_v2(temppath)
         p = Pack.from_objects(data, load_pack_index(temppath))
 
-        # Write a full pack version
-        temppath = os.path.join(self.pack_dir, 
-            sha_to_hex(urllib2.randombytes(20))+".temppack")
-        write_pack(temppath, ((o, None) for o in p.iterobjects(self.get_raw)), 
-                len(p))
+        try:
+            # Write a full pack version
+            temppath = os.path.join(self.pack_dir,
+                sha_to_hex(urllib2.randombytes(20))+".temppack")
+            write_pack(temppath, ((o, None) for o in p.iterobjects()), len(p))
+        finally:
+            p.close()
+
         pack_sha = load_pack_index(temppath+".idx").objects_sha1()
         newbasename = os.path.join(self.pack_dir, "pack-%s" % pack_sha)
         os.rename(temppath+".pack", newbasename+".pack")
         os.rename(temppath+".idx", newbasename+".idx")
-        self._add_known_pack(newbasename)
+        final_pack = Pack(newbasename)
+        self._add_known_pack(final_pack)
+        return final_pack
 
     def move_in_pack(self, path):
         """Move a specific file containing a pack into the pack directory.
 
-        :note: The file should be on the same file system as the 
+        :note: The file should be on the same file system as the
             packs directory.
 
         :param path: Path to the pack file.
         """
         p = PackData(path)
         entries = p.sorted_entries()
-        basename = os.path.join(self.pack_dir, 
+        basename = os.path.join(self.pack_dir,
             "pack-%s" % iter_sha1(entry[0] for entry in entries))
-        write_pack_index_v2(basename+".idx", entries, p.get_stored_checksum())
+        f = GitFile(basename+".idx", "wb")
+        try:
+            write_pack_index_v2(f, entries, p.get_stored_checksum())
+        finally:
+            f.close()
         p.close()
         os.rename(path, basename + ".pack")
-        self._add_known_pack(basename)
+        final_pack = Pack(basename)
+        self._add_known_pack(final_pack)
+        return final_pack
 
     def add_thin_pack(self):
         """Add a new thin pack to this object store.
 
-        Thin packs are packs that contain deltas with parents that exist 
+        Thin packs are packs that contain deltas with parents that exist
         in a different pack.
         """
         fd, path = tempfile.mkstemp(dir=self.pack_dir, suffix=".pack")
@@ -382,13 +452,16 @@
             os.fsync(fd)
             f.close()
             if os.path.getsize(path) > 0:
-                self.move_in_thin_pack(path)
+                return self.move_in_thin_pack(path)
+            else:
+                os.remove(path)
+                return None
         return f, commit
 
     def add_pack(self):
-        """Add a new pack to this object store. 
+        """Add a new pack to this object store.
 
-        :return: Fileobject to write to and a commit function to 
+        :return: Fileobject to write to and a commit function to
             call when the pack is finished.
         """
         fd, path = tempfile.mkstemp(dir=self.pack_dir, suffix=".pack")
@@ -397,7 +470,10 @@
             os.fsync(fd)
             f.close()
             if os.path.getsize(path) > 0:
-                self.move_in_pack(path)
+                return self.move_in_pack(path)
+            else:
+                os.remove(path)
+                return None
         return f, commit
 
     def add_object(self, obj):
@@ -405,19 +481,31 @@
 
         :param obj: Object to add
         """
-        self._add_shafile(obj.id, obj)
-
-    def add_objects(self, objects):
-        """Add a set of objects to this object store.
-
-        :param objects: Iterable over objects, should support __len__.
-        """
-        if len(objects) == 0:
-            # Don't bother writing an empty pack file
-            return
-        f, commit = self.add_pack()
-        write_pack_data(f, objects, len(objects))
-        commit()
+        dir = os.path.join(self.path, obj.id[:2])
+        try:
+            os.mkdir(dir)
+        except OSError, e:
+            if e.errno != errno.EEXIST:
+                raise
+        path = os.path.join(dir, obj.id[2:])
+        if os.path.exists(path):
+            return # Already there, no need to write again
+        f = GitFile(path, 'wb')
+        try:
+            f.write(obj.as_legacy_object())
+        finally:
+            f.close()
+
+    @classmethod
+    def init(cls, path):
+        try:
+            os.mkdir(path)
+        except OSError, e:
+            if e.errno != errno.EEXIST:
+                raise
+        os.mkdir(os.path.join(path, "info"))
+        os.mkdir(os.path.join(path, PACKDIR))
+        return cls(path)
 
 
 class MemoryObjectStore(BaseObjectStore):
@@ -427,25 +515,38 @@
         super(MemoryObjectStore, self).__init__()
         self._data = {}
 
-    def __contains__(self, sha):
-        """Check if the object with a particular SHA is present."""
+    def contains_loose(self, sha):
+        """Check if a particular object is present by SHA1 and is loose."""
         return sha in self._data
 
+    def contains_packed(self, sha):
+        """Check if a particular object is present by SHA1 and is packed."""
+        return False
+
     def __iter__(self):
         """Iterate over the SHAs that are present in this store."""
         return self._data.iterkeys()
 
+    @property
+    def packs(self):
+        """List with pack objects."""
+        return []
+
     def get_raw(self, name):
         """Obtain the raw text for an object.
-        
+
         :param name: sha for the object.
-        :return: tuple with object type and object contents.
+        :return: tuple with numeric type and object contents.
         """
         return self[name].as_raw_string()
 
     def __getitem__(self, name):
         return self._data[name]
 
+    def __delitem__(self, name):
+        """Delete an object from this store, for testing only."""
+        del self._data[name]
+
     def add_object(self, obj):
         """Add a single object to this object store.
 
@@ -476,7 +577,7 @@
         raise NotImplementedError(self.add_object)
 
     def finish(self, object):
-        """Finish the imoprt and write objects to disk."""
+        """Finish the import and write objects to disk."""
         raise NotImplementedError(self.finish)
 
 
@@ -521,7 +622,7 @@
     def __contains__(self, needle):
         """Check if an object is present.
 
-        :note: This checks if the object is present in 
+        :note: This checks if the object is present in
             the underlying object store, not if it would
             be yielded by the iterator.
 
@@ -531,7 +632,7 @@
 
     def __getitem__(self, key):
         """Find an object by SHA1.
-        
+
         :note: This retrieves the object from the underlying
             object store. It will also succeed if the object would
             not be returned by the iterator.
@@ -552,9 +653,10 @@
     """
     parts = path.split("/")
     sha = root_sha
+    mode = None
     for p in parts:
         obj = lookup_obj(sha)
-        if type(obj) is not Tree:
+        if not isinstance(obj, Tree):
             raise NotTreeError(sha)
         if p == '':
             continue
@@ -565,27 +667,37 @@
 class MissingObjectFinder(object):
     """Find the objects missing from another object store.
 
-    :param object_store: Object store containing at least all objects to be 
+    :param object_store: Object store containing at least all objects to be
         sent
     :param haves: SHA1s of commits not to send (already present in target)
     :param wants: SHA1s of commits to send
     :param progress: Optional function to report progress to.
+    :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+        sha for including tags.
+    :param tagged: dict of pointed-to sha -> tag sha for including tags
     """
 
-    def __init__(self, object_store, haves, wants, progress=None):
-        self.sha_done = set(haves)
-        self.objects_to_send = set([(w, None, False) for w in wants if w not in haves])
+    def __init__(self, object_store, haves, wants, progress=None,
+                 get_tagged=None):
+        haves = set(haves)
+        self.sha_done = haves
+        self.objects_to_send = set([(w, None, False) for w in wants
+                                    if w not in haves])
         self.object_store = object_store
         if progress is None:
             self.progress = lambda x: None
         else:
             self.progress = progress
+        self._tagged = get_tagged and get_tagged() or {}
 
     def add_todo(self, entries):
-        self.objects_to_send.update([e for e in entries if not e[0] in self.sha_done])
+        self.objects_to_send.update([e for e in entries
+                                     if not e[0] in self.sha_done])
 
     def parse_tree(self, tree):
-        self.add_todo([(sha, name, not stat.S_ISDIR(mode)) for (mode, name, sha) in tree.entries() if not S_ISGITLINK(mode)])
+        self.add_todo([(sha, name, not stat.S_ISDIR(mode))
+                       for mode, name, sha in tree.entries()
+                       if not S_ISGITLINK(mode)])
 
     def parse_commit(self, commit):
         self.add_todo([(commit.tree, "", False)])
@@ -606,13 +718,19 @@
                 self.parse_tree(o)
             elif isinstance(o, Tag):
                 self.parse_tag(o)
+        if sha in self._tagged:
+            self.add_todo([(self._tagged[sha], None, True)])
         self.sha_done.add(sha)
         self.progress("counting objects: %d\r" % len(self.sha_done))
         return (sha, name)
 
 
 class ObjectStoreGraphWalker(object):
-    """Graph walker that finds out what commits are missing from an object store."""
+    """Graph walker that finds what commits are missing from an object store.
+
+    :ivar heads: Revisions without descendants in the local repo
+    :ivar get_parents: Function to retrieve parents in the local repo
+    """
 
     def __init__(self, local_heads, get_parents):
         """Create a new instance.
@@ -625,12 +743,26 @@
         self.parents = {}
 
     def ack(self, sha):
-        """Ack that a particular revision and its ancestors are present in the source."""
-        if sha in self.heads:
-            self.heads.remove(sha)
-        if sha in self.parents:
-            for p in self.parents[sha]:
-                self.ack(p)
+        """Ack that a revision and its ancestors are present in the source."""
+        ancestors = set([sha])
+
+        # stop if we run out of heads to remove
+        while self.heads:
+            for a in ancestors:
+                if a in self.heads:
+                    self.heads.remove(a)
+
+            # collect all ancestors
+            new_ancestors = set()
+            for a in ancestors:
+                if a in self.parents:
+                    new_ancestors.update(self.parents[a])
+
+            # no more ancestors; stop
+            if not new_ancestors:
+                break
+
+            ancestors = new_ancestors
 
     def next(self):
         """Iterate over ancestors of heads in the target."""

=== modified file 'dulwich/objects.py'
--- dulwich/objects.py	2009-10-24 21:59:01 +0000
+++ dulwich/objects.py	2010-12-19 15:56:03 +0000
@@ -1,23 +1,22 @@
 # objects.py -- Access to base git objects
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
 # Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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) a 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.
 
-
 """Access to base git objects."""
 
 
@@ -25,37 +24,47 @@
 from cStringIO import (
     StringIO,
     )
-import mmap
 import os
+import posixpath
 import stat
-import time
 import zlib
 
 from dulwich.errors import (
+    ChecksumMismatch,
     NotBlobError,
     NotCommitError,
+    NotTagError,
     NotTreeError,
+    ObjectFormatException,
     )
-from dulwich.misc import (
+from dulwich.file import GitFile
+from dulwich._compat import (
     make_sha,
+    TreeEntryTuple,
     )
 
-BLOB_ID = "blob"
-TAG_ID = "tag"
-TREE_ID = "tree"
-COMMIT_ID = "commit"
-PARENT_ID = "parent"
-AUTHOR_ID = "author"
-COMMITTER_ID = "committer"
-OBJECT_ID = "object"
-TYPE_ID = "type"
-TAGGER_ID = "tagger"
-ENCODING_ID = "encoding"
-
-S_IFGITLINK	= 0160000
+
+# Header fields for commits
+_TREE_HEADER = "tree"
+_PARENT_HEADER = "parent"
+_AUTHOR_HEADER = "author"
+_COMMITTER_HEADER = "committer"
+_ENCODING_HEADER = "encoding"
+
+
+# Header fields for objects
+_OBJECT_HEADER = "object"
+_TYPE_HEADER = "type"
+_TAG_HEADER = "tag"
+_TAGGER_HEADER = "tagger"
+
+
+S_IFGITLINK = 0160000
+
 def S_ISGITLINK(m):
     return (stat.S_IFMT(m) == S_IFGITLINK)
 
+
 def _decompress(string):
     dcomp = zlib.decompressobj()
     dcomped = dcomp.decompress(string)
@@ -76,6 +85,32 @@
     return binascii.unhexlify(hex)
 
 
+def hex_to_filename(path, hex):
+    """Takes a hex sha and returns its filename relative to the given path."""
+    dir = hex[:2]
+    file = hex[2:]
+    # Check from object dir
+    return os.path.join(path, dir, file)
+
+
+def filename_to_hex(filename):
+    """Takes an object filename and returns its corresponding hex sha."""
+    # grab the last (up to) two path components
+    names = filename.rsplit(os.path.sep, 2)[-2:]
+    errmsg = "Invalid object filename: %s" % filename
+    assert len(names) == 2, errmsg
+    base, rest = names
+    assert len(base) == 2 and len(rest) == 38, errmsg
+    hex = base + rest
+    hex_to_sha(hex)
+    return hex
+
+
+def object_header(num_type, length):
+    """Return an object header for the given numeric type and text length."""
+    return "%s %d\0" % (object_class(num_type).type_name, length)
+
+
 def serializable_property(name, docstring=None):
     def set(obj, value):
         obj._ensure_parsed()
@@ -87,44 +122,113 @@
     return property(get, set, doc=docstring)
 
 
+def object_class(type):
+    """Get the object class corresponding to the given type.
+
+    :param type: Either a type name string or a numeric type.
+    :return: The ShaFile subclass corresponding to the given type, or None if
+        type is not a valid type name/number.
+    """
+    return _TYPE_MAP.get(type, None)
+
+
+def check_hexsha(hex, error_msg):
+    try:
+        hex_to_sha(hex)
+    except (TypeError, AssertionError):
+        raise ObjectFormatException("%s %s" % (error_msg, hex))
+
+
+def check_identity(identity, error_msg):
+    """Check if the specified identity is valid.
+
+    This will raise an exception if the identity is not valid.
+
+    :param identity: Identity string
+    :param error_msg: Error message to use in exception
+    """
+    email_start = identity.find("<")
+    email_end = identity.find(">")
+    if (email_start < 0 or email_end < 0 or email_end <= email_start
+        or identity.find("<", email_start + 1) >= 0
+        or identity.find(">", email_end + 1) >= 0
+        or not identity.endswith(">")):
+        raise ObjectFormatException(error_msg)
+
+
+class FixedSha(object):
+    """SHA object that behaves like hashlib's but is given a fixed value."""
+
+    __slots__ = ('_hexsha', '_sha')
+
+    def __init__(self, hexsha):
+        self._hexsha = hexsha
+        self._sha = hex_to_sha(hexsha)
+
+    def digest(self):
+        return self._sha
+
+    def hexdigest(self):
+        return self._hexsha
+
+
 class ShaFile(object):
     """A git SHA file."""
-  
-    @classmethod
-    def _parse_legacy_object(cls, map):
-        """Parse a legacy object, creating it and setting object._text"""
+
+    __slots__ = ('_needs_parsing', '_chunked_text', '_file', '_path',
+                 '_sha', '_needs_serialization', '_magic')
+
+    @staticmethod
+    def _parse_legacy_object_header(magic, f):
+        """Parse a legacy object, creating it but not reading the file."""
+        bufsize = 1024
+        decomp = zlib.decompressobj()
+        header = decomp.decompress(magic)
+        start = 0
+        end = -1
+        while end < 0:
+            extra = f.read(bufsize)
+            header += decomp.decompress(extra)
+            magic += extra
+            end = header.find("\0", start)
+            start = len(header)
+        header = header[:end]
+        type_name, size = header.split(" ", 1)
+        size = int(size)  # sanity check
+        obj_class = object_class(type_name)
+        if not obj_class:
+            raise ObjectFormatException("Not a known type: %s" % type_name)
+        ret = obj_class()
+        ret._magic = magic
+        return ret
+
+    def _parse_legacy_object(self, map):
+        """Parse a legacy object, setting the raw string."""
         text = _decompress(map)
-        object = None
-        for posstype in type_map.keys():
-            if text.startswith(posstype):
-                object = type_map[posstype]()
-                text = text[len(posstype):]
-                break
-        assert object is not None, "%s is not a known object type" % text[:9]
-        assert text[0] == ' ', "%s is not a space" % text[0]
-        text = text[1:]
-        size = 0
-        i = 0
-        while text[0] >= '0' and text[0] <= '9':
-            if i > 0 and size == 0:
-                raise AssertionError("Size is not in canonical format")
-            size = (size * 10) + int(text[0])
-            text = text[1:]
-            i += 1
-        object._size = size
-        assert text[0] == "\0", "Size not followed by null"
-        text = text[1:]
-        object.set_raw_string(text)
-        return object
+        header_end = text.find('\0')
+        if header_end < 0:
+            raise ObjectFormatException("Invalid object header, no \\0")
+        self.set_raw_string(text[header_end+1:])
+
+    def as_legacy_object_chunks(self):
+        compobj = zlib.compressobj()
+        yield compobj.compress(self._header())
+        for chunk in self.as_raw_chunks():
+            yield compobj.compress(chunk)
+        yield compobj.flush()
 
     def as_legacy_object(self):
-        text = self.as_raw_string()
-        return zlib.compress("%s %d\0%s" % (self._type, len(text), text))
-  
+        return "".join(self.as_legacy_object_chunks())
+
+    def as_raw_chunks(self):
+        if self._needs_parsing:
+            self._ensure_parsed()
+        elif self._needs_serialization:
+            self._chunked_text = self._serialize()
+        return self._chunked_text
+
     def as_raw_string(self):
-        if self._needs_serialization:
-            self.serialize()
-        return self._text
+        return "".join(self.as_raw_chunks())
 
     def __str__(self):
         return self.as_raw_string()
@@ -137,106 +241,237 @@
 
     def _ensure_parsed(self):
         if self._needs_parsing:
-            self._parse_text()
+            if not self._chunked_text:
+                if self._file is not None:
+                    self._parse_file(self._file)
+                    self._file = None
+                elif self._path is not None:
+                    self._parse_path()
+                else:
+                    raise AssertionError(
+                        "ShaFile needs either text or filename")
+            self._deserialize(self._chunked_text)
+            self._needs_parsing = False
 
     def set_raw_string(self, text):
         if type(text) != str:
             raise TypeError(text)
-        self._text = text
+        self.set_raw_chunks([text])
+
+    def set_raw_chunks(self, chunks):
+        self._chunked_text = chunks
+        self._deserialize(chunks)
         self._sha = None
-        self._needs_parsing = True
+        self._needs_parsing = False
         self._needs_serialization = False
-  
-    @classmethod
-    def _parse_object(cls, map):
-        """Parse a new style object , creating it and setting object._text"""
-        used = 0
-        byte = ord(map[used])
-        used += 1
-        num_type = (byte >> 4) & 7
-        try:
-            object = num_type_map[num_type]()
-        except KeyError:
-            raise AssertionError("Not a known type: %d" % num_type)
+
+    @staticmethod
+    def _parse_object_header(magic, f):
+        """Parse a new style object, creating it but not reading the file."""
+        num_type = (ord(magic[0]) >> 4) & 7
+        obj_class = object_class(num_type)
+        if not obj_class:
+            raise ObjectFormatException("Not a known type %d" % num_type)
+        ret = obj_class()
+        ret._magic = magic
+        return ret
+
+    def _parse_object(self, map):
+        """Parse a new style object, setting self._text."""
+        # skip type and size; type must have already been determined, and
+        # we trust zlib to fail if it's otherwise corrupted
+        byte = ord(map[0])
+        used = 1
         while (byte & 0x80) != 0:
             byte = ord(map[used])
             used += 1
         raw = map[used:]
-        object.set_raw_string(_decompress(raw))
-        return object
-  
-    @classmethod
-    def _parse_file(cls, map):
-        word = (ord(map[0]) << 8) + ord(map[1])
-        if ord(map[0]) == 0x78 and (word % 31) == 0:
-            return cls._parse_legacy_object(map)
+        self.set_raw_string(_decompress(raw))
+
+    @classmethod
+    def _is_legacy_object(cls, magic):
+        b0, b1 = map(ord, magic)
+        word = (b0 << 8) + b1
+        return b0 == 0x78 and (word % 31) == 0
+
+    @classmethod
+    def _parse_file_header(cls, f):
+        magic = f.read(2)
+        if cls._is_legacy_object(magic):
+            return cls._parse_legacy_object_header(magic, f)
         else:
-            return cls._parse_object(map)
-  
+            return cls._parse_object_header(magic, f)
+
     def __init__(self):
         """Don't call this directly"""
         self._sha = None
-  
-    def _parse_text(self):
-        """For subclasses to do initialisation time parsing"""
-  
-    @classmethod
-    def from_file(cls, filename):
-        """Get the contents of a SHA file on disk"""
-        size = os.path.getsize(filename)
-        f = open(filename, 'rb')
-        try:
-            map = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
-            shafile = cls._parse_file(map)
-            return shafile
-        finally:
-            f.close()
-  
-    @classmethod
-    def from_raw_string(cls, type, string):
+        self._path = None
+        self._file = None
+        self._magic = None
+        self._chunked_text = []
+        self._needs_parsing = False
+        self._needs_serialization = True
+
+    def _deserialize(self, chunks):
+        raise NotImplementedError(self._deserialize)
+
+    def _serialize(self):
+        raise NotImplementedError(self._serialize)
+
+    def _parse_path(self):
+        f = GitFile(self._path, 'rb')
+        try:
+            self._parse_file(f)
+        finally:
+            f.close()
+
+    def _parse_file(self, f):
+        magic = self._magic
+        if magic is None:
+            magic = f.read(2)
+        map = magic + f.read()
+        if self._is_legacy_object(magic[:2]):
+            self._parse_legacy_object(map)
+        else:
+            self._parse_object(map)
+
+    @classmethod
+    def from_path(cls, path):
+        f = GitFile(path, 'rb')
+        try:
+            obj = cls.from_file(f)
+            obj._path = path
+            obj._sha = FixedSha(filename_to_hex(path))
+            obj._file = None
+            obj._magic = None
+            return obj
+        finally:
+            f.close()
+
+    @classmethod
+    def from_file(cls, f):
+        """Get the contents of a SHA file on disk."""
+        try:
+            obj = cls._parse_file_header(f)
+            obj._sha = None
+            obj._needs_parsing = True
+            obj._needs_serialization = True
+            obj._file = f
+            return obj
+        except (IndexError, ValueError), e:
+            raise ObjectFormatException("invalid object header")
+
+    @staticmethod
+    def from_raw_string(type_num, string):
         """Creates an object of the indicated type from the raw string given.
-    
-        Type is the numeric type of an object. String is the raw uncompressed
-        contents.
-        """
-        real_class = num_type_map[type]
-        obj = real_class()
-        obj.type = type
-        obj.set_raw_string(string)
-        return obj
-  
+
+        :param type_num: The numeric type of the object.
+        :param string: The raw uncompressed contents.
+        """
+        obj = object_class(type_num)()
+        obj.set_raw_string(string)
+        return obj
+
+    @staticmethod
+    def from_raw_chunks(type_num, chunks):
+        """Creates an object of the indicated type from the raw chunks given.
+
+        :param type_num: The numeric type of the object.
+        :param chunks: An iterable of the raw uncompressed contents.
+        """
+        obj = object_class(type_num)()
+        obj.set_raw_chunks(chunks)
+        return obj
+
+    @classmethod
+    def from_string(cls, string):
+        """Create a ShaFile from a string."""
+        obj = cls()
+        obj.set_raw_string(string)
+        return obj
+
+    def _check_has_member(self, member, error_msg):
+        """Check that the object has a given member variable.
+
+        :param member: the member variable to check for
+        :param error_msg: the message for an error if the member is missing
+        :raise ObjectFormatException: with the given error_msg if member is
+            missing or is None
+        """
+        if getattr(self, member, None) is None:
+            raise ObjectFormatException(error_msg)
+
+    def check(self):
+        """Check this object for internal consistency.
+
+        :raise ObjectFormatException: if the object is malformed in some way
+        :raise ChecksumMismatch: if the object was created with a SHA that does
+            not match its contents
+        """
+        # TODO: if we find that error-checking during object parsing is a
+        # performance bottleneck, those checks should be moved to the class's
+        # check() method during optimization so we can still check the object
+        # when necessary.
+        old_sha = self.id
+        try:
+            self._deserialize(self.as_raw_chunks())
+            self._sha = None
+            new_sha = self.id
+        except Exception, e:
+            raise ObjectFormatException(e)
+        if old_sha != new_sha:
+            raise ChecksumMismatch(new_sha, old_sha)
+
     def _header(self):
-        return "%s %lu\0" % (self._type, len(self.as_raw_string()))
-  
+        return object_header(self.type, self.raw_length())
+
+    def raw_length(self):
+        """Returns the length of the raw string of this object."""
+        ret = 0
+        for chunk in self.as_raw_chunks():
+            ret += len(chunk)
+        return ret
+
+    def _make_sha(self):
+        ret = make_sha()
+        ret.update(self._header())
+        for chunk in self.as_raw_chunks():
+            ret.update(chunk)
+        return ret
+
     def sha(self):
         """The SHA1 object that is the name of this object."""
-        if self._needs_serialization or self._sha is None:
-            self._sha = make_sha()
-            self._sha.update(self._header())
-            self._sha.update(self.as_raw_string())
+        if self._sha is None or self._needs_serialization:
+            # this is a local because as_raw_chunks() overwrites self._sha
+            new_sha = make_sha()
+            new_sha.update(self._header())
+            for chunk in self.as_raw_chunks():
+                new_sha.update(chunk)
+            self._sha = new_sha
         return self._sha
-  
+
     @property
     def id(self):
         return self.sha().hexdigest()
-  
+
     def get_type(self):
-        return self._num_type
+        return self.type_num
 
     def set_type(self, type):
-        self._num_type = type
+        self.type_num = type
 
+    # DEPRECATED: use type_num or type_name as needed.
     type = property(get_type, set_type)
-  
+
     def __repr__(self):
         return "<%s %s>" % (self.__class__.__name__, self.id)
 
     def __ne__(self, other):
         return self.id != other.id
-  
+
     def __eq__(self, other):
-        """Return true id the sha of the two objects match.
-  
+        """Return true if the sha of the two objects match.
+
         The __le__ etc methods aren't overriden as they make no sense,
         certainly at this level.
         """
@@ -246,175 +481,306 @@
 class Blob(ShaFile):
     """A Git Blob object."""
 
-    _type = BLOB_ID
-    _num_type = 3
-    _needs_serialization = False
-    _needs_parsing = False
-
-    def get_data(self):
-        return self._text
-
-    def set_data(self, data):
-        self._text = data
-
-    data = property(get_data, set_data, 
-            "The text contained within the blob object.")
+    __slots__ = ()
+
+    type_name = 'blob'
+    type_num = 3
+
+    def __init__(self):
+        super(Blob, self).__init__()
+        self._chunked_text = []
+        self._needs_parsing = False
+        self._needs_serialization = False
+
+    def _get_data(self):
+        return self.as_raw_string()
+
+    def _set_data(self, data):
+        self.set_raw_string(data)
+
+    data = property(_get_data, _set_data,
+                    "The text contained within the blob object.")
+
+    def _get_chunked(self):
+        self._ensure_parsed()
+        return self._chunked_text
+
+    def _set_chunked(self, chunks):
+        self._chunked_text = chunks
+
+    def _serialize(self):
+        if not self._chunked_text:
+            self._ensure_parsed()
+        self._needs_serialization = False
+        return self._chunked_text
+
+    def _deserialize(self, chunks):
+        self._chunked_text = chunks
+
+    chunked = property(_get_chunked, _set_chunked,
+        "The text within the blob object, as chunks (not necessarily lines).")
 
     @classmethod
-    def from_file(cls, filename):
-        blob = ShaFile.from_file(filename)
-        if blob._type != cls._type:
-            raise NotBlobError(filename)
+    def from_path(cls, path):
+        blob = ShaFile.from_path(path)
+        if not isinstance(blob, cls):
+            raise NotBlobError(path)
         return blob
 
-    @classmethod
-    def from_string(cls, string):
-        """Create a blob from a string."""
-        shafile = cls()
-        shafile.set_raw_string(string)
-        return shafile
+    def check(self):
+        """Check this object for internal consistency.
+
+        :raise ObjectFormatException: if the object is malformed in some way
+        """
+        super(Blob, self).check()
+
+
+def _parse_tag_or_commit(text):
+    """Parse tag or commit text.
+
+    :param text: the raw text of the tag or commit object.
+    :return: iterator of tuples of (field, value), one per header line, in the
+        order read from the text, possibly including duplicates. Includes a
+        field named None for the freeform tag/commit text.
+    """
+    f = StringIO(text)
+    for l in f:
+        l = l.rstrip("\n")
+        if l == "":
+            # Empty line indicates end of headers
+            break
+        yield l.split(" ", 1)
+    yield (None, f.read())
+    f.close()
+
+
+def parse_tag(text):
+    return _parse_tag_or_commit(text)
 
 
 class Tag(ShaFile):
     """A Git Tag object."""
 
-    _type = TAG_ID
-    _num_type = 4
+    type_name = 'tag'
+    type_num = 4
+
+    __slots__ = ('_tag_timezone_neg_utc', '_name', '_object_sha',
+                 '_object_class', '_tag_time', '_tag_timezone',
+                 '_tagger', '_message')
 
     def __init__(self):
         super(Tag, self).__init__()
-        self._needs_parsing = False
-        self._needs_serialization = True
-
-    @classmethod
-    def from_file(cls, filename):
-        blob = ShaFile.from_file(filename)
-        if blob._type != cls._type:
-            raise NotBlobError(filename)
-        return blob
-
-    @classmethod
-    def from_string(cls, string):
-        """Create a blob from a string."""
-        shafile = cls()
-        shafile.set_raw_string(string)
-        return shafile
-
-    def serialize(self):
-        f = StringIO()
-        f.write("%s %s\n" % (OBJECT_ID, self._object_sha))
-        f.write("%s %s\n" % (TYPE_ID, num_type_map[self._object_type]._type))
-        f.write("%s %s\n" % (TAG_ID, self._name))
+        self._tag_timezone_neg_utc = False
+
+    @classmethod
+    def from_path(cls, filename):
+        tag = ShaFile.from_path(filename)
+        if not isinstance(tag, cls):
+            raise NotTagError(filename)
+        return tag
+
+    def check(self):
+        """Check this object for internal consistency.
+
+        :raise ObjectFormatException: if the object is malformed in some way
+        """
+        super(Tag, self).check()
+        self._check_has_member("_object_sha", "missing object sha")
+        self._check_has_member("_object_class", "missing object type")
+        self._check_has_member("_name", "missing tag name")
+
+        if not self._name:
+            raise ObjectFormatException("empty tag name")
+
+        check_hexsha(self._object_sha, "invalid object sha")
+
+        if getattr(self, "_tagger", None):
+            check_identity(self._tagger, "invalid tagger")
+
+        last = None
+        for field, _ in parse_tag("".join(self._chunked_text)):
+            if field == _OBJECT_HEADER and last is not None:
+                raise ObjectFormatException("unexpected object")
+            elif field == _TYPE_HEADER and last != _OBJECT_HEADER:
+                raise ObjectFormatException("unexpected type")
+            elif field == _TAG_HEADER and last != _TYPE_HEADER:
+                raise ObjectFormatException("unexpected tag name")
+            elif field == _TAGGER_HEADER and last != _TAG_HEADER:
+                raise ObjectFormatException("unexpected tagger")
+            last = field
+
+    def _serialize(self):
+        chunks = []
+        chunks.append("%s %s\n" % (_OBJECT_HEADER, self._object_sha))
+        chunks.append("%s %s\n" % (_TYPE_HEADER, self._object_class.type_name))
+        chunks.append("%s %s\n" % (_TAG_HEADER, self._name))
         if self._tagger:
             if self._tag_time is None:
-                f.write("%s %s\n" % (TAGGER_ID, self._tagger))
+                chunks.append("%s %s\n" % (_TAGGER_HEADER, self._tagger))
             else:
-                f.write("%s %s %d %s\n" % (TAGGER_ID, self._tagger, self._tag_time, format_timezone(self._tag_timezone)))
-        f.write("\n") # To close headers
-        f.write(self._message)
-        self._text = f.getvalue()
-        self._needs_serialization = False
+                chunks.append("%s %s %d %s\n" % (
+                  _TAGGER_HEADER, self._tagger, self._tag_time,
+                  format_timezone(self._tag_timezone,
+                    self._tag_timezone_neg_utc)))
+        chunks.append("\n") # To close headers
+        chunks.append(self._message)
+        return chunks
 
-    def _parse_text(self):
+    def _deserialize(self, chunks):
         """Grab the metadata attached to the tag"""
         self._tagger = None
-        f = StringIO(self._text)
-        for l in f:
-            l = l.rstrip("\n")
-            if l == "":
-                break # empty line indicates end of headers
-            (field, value) = l.split(" ", 1)
-            if field == OBJECT_ID:
+        for field, value in parse_tag("".join(chunks)):
+            if field == _OBJECT_HEADER:
                 self._object_sha = value
-            elif field == TYPE_ID:
-                self._object_type = type_map[value]
-            elif field == TAG_ID:
+            elif field == _TYPE_HEADER:
+                obj_class = object_class(value)
+                if not obj_class:
+                    raise ObjectFormatException("Not a known type: %s" % value)
+                self._object_class = obj_class
+            elif field == _TAG_HEADER:
                 self._name = value
-            elif field == TAGGER_ID:
+            elif field == _TAGGER_HEADER:
                 try:
                     sep = value.index("> ")
                 except ValueError:
                     self._tagger = value
                     self._tag_time = None
                     self._tag_timezone = None
+                    self._tag_timezone_neg_utc = False
                 else:
                     self._tagger = value[0:sep+1]
-                    (timetext, timezonetext) = value[sep+2:].rsplit(" ", 1)
                     try:
+                        (timetext, timezonetext) = value[sep+2:].rsplit(" ", 1)
                         self._tag_time = int(timetext)
-                    except ValueError: #Not a unix timestamp
-                        self._tag_time = time.strptime(timetext)
-                    self._tag_timezone = parse_timezone(timezonetext)
+                        self._tag_timezone, self._tag_timezone_neg_utc = \
+                                parse_timezone(timezonetext)
+                    except ValueError, e:
+                        raise ObjectFormatException(e)
+            elif field is None:
+                self._message = value
             else:
-                raise AssertionError("Unknown field %s" % field)
-        self._message = f.read()
-        self._needs_parsing = False
-
-    def get_object(self):
-        """Returns the object pointed by this tag, represented as a tuple(type, sha)"""
-        self._ensure_parsed()
-        return (self._object_type, self._object_sha)
-
-    def set_object(self, value):
-        self._ensure_parsed()
-        (self._object_type, self._object_sha) = value
+                raise ObjectFormatException("Unknown field %s" % field)
+
+    def _get_object(self):
+        """Get the object pointed to by this tag.
+
+        :return: tuple of (object class, sha).
+        """
+        self._ensure_parsed()
+        return (self._object_class, self._object_sha)
+
+    def _set_object(self, value):
+        self._ensure_parsed()
+        (self._object_class, self._object_sha) = value
         self._needs_serialization = True
 
-    object = property(get_object, set_object)
+    object = property(_get_object, _set_object)
 
     name = serializable_property("name", "The name of this tag")
-    tagger = serializable_property("tagger", 
+    tagger = serializable_property("tagger",
         "Returns the name of the person who created this tag")
-    tag_time = serializable_property("tag_time", 
+    tag_time = serializable_property("tag_time",
         "The creation timestamp of the tag.  As the number of seconds since the epoch")
-    tag_timezone = serializable_property("tag_timezone", 
+    tag_timezone = serializable_property("tag_timezone",
         "The timezone that tag_time is in.")
     message = serializable_property("message", "The message attached to this tag")
 
 
-def parse_tree(text):
-    ret = {}
+class TreeEntry(TreeEntryTuple):
+    """Namedtuple encapsulating a single tree entry."""
+
+    def in_path(self, path):
+        """Return a copy of this entry with the given path prepended."""
+        return TreeEntry(posixpath.join(path, self.path), self.mode, self.sha)
+
+
+def parse_tree(text, strict=False):
+    """Parse a tree text.
+
+    :param text: Serialized text to parse
+    :return: iterator of tuples of (name, mode, sha)
+    :raise ObjectFormatException: if the object was malformed in some way
+    """
     count = 0
-    while count < len(text):
-        mode = 0
-        chr = text[count]
-        while chr != ' ':
-            assert chr >= '0' and chr <= '7', "%s is not a valid mode char" % chr
-            mode = (mode << 3) + (ord(chr) - ord('0'))
-            count += 1
-            chr = text[count]
-        count += 1
-        chr = text[count]
-        name = ''
-        while chr != '\0':
-            name += chr
-            count += 1
-            chr = text[count]
-        count += 1
-        chr = text[count]
-        sha = text[count:count+20]
+    l = len(text)
+    while count < l:
+        mode_end = text.index(' ', count)
+        mode_text = text[count:mode_end]
+        if strict and mode_text.startswith('0'):
+            raise ObjectFormatException("Invalid mode '%s'" % mode_text)
+        try:
+            mode = int(mode_text, 8)
+        except ValueError:
+            raise ObjectFormatException("Invalid mode '%s'" % mode_text)
+        name_end = text.index('\0', mode_end)
+        name = text[mode_end+1:name_end]
+        count = name_end+21
+        sha = text[name_end+1:count]
+        if len(sha) != 20:
+            raise ObjectFormatException("Sha has invalid length")
         hexsha = sha_to_hex(sha)
-        ret[name] = (mode, hexsha)
-        count = count + 20
-    return ret
+        yield (name, mode, hexsha)
+
+
+def serialize_tree(items):
+    """Serialize the items in a tree to a text.
+
+    :param items: Sorted iterable over (name, mode, sha) tuples
+    :return: Serialized tree text as chunks
+    """
+    for name, mode, hexsha in items:
+        yield "%04o %s\0%s" % (mode, name, hex_to_sha(hexsha))
+
+
+def sorted_tree_items(entries, name_order):
+    """Iterate over a tree entries dictionary.
+
+    :param name_order: If True, iterate entries in order of their name. If
+        False, iterate entries in tree order, that is, treat subtree entries as
+        having '/' appended.
+    :param entries: Dictionary mapping names to (mode, sha) tuples
+    :return: Iterator over (name, mode, hexsha)
+    """
+    cmp_func = name_order and cmp_entry_name_order or cmp_entry
+    for name, entry in sorted(entries.iteritems(), cmp=cmp_func):
+        mode, hexsha = entry
+        # Stricter type checks than normal to mirror checks in the C version.
+        mode = int(mode)
+        if not isinstance(hexsha, str):
+            raise TypeError('Expected a string for SHA, got %r' % hexsha)
+        yield TreeEntry(name, mode, hexsha)
+
+
+def cmp_entry((name1, value1), (name2, value2)):
+    """Compare two tree entries in tree order."""
+    if stat.S_ISDIR(value1[0]):
+        name1 += "/"
+    if stat.S_ISDIR(value2[0]):
+        name2 += "/"
+    return cmp(name1, name2)
+
+
+def cmp_entry_name_order(entry1, entry2):
+    """Compare two tree entries in name order."""
+    return cmp(entry1[0], entry2[0])
 
 
 class Tree(ShaFile):
     """A Git tree object"""
 
-    _type = TREE_ID
-    _num_type = 2
+    type_name = 'tree'
+    type_num = 2
+
+    __slots__ = ('_entries')
 
     def __init__(self):
         super(Tree, self).__init__()
         self._entries = {}
-        self._needs_parsing = False
-        self._needs_serialization = True
 
     @classmethod
-    def from_file(cls, filename):
-        tree = ShaFile.from_file(filename)
-        if tree._type != cls._type:
+    def from_path(cls, filename):
+        tree = ShaFile.from_path(filename)
+        if not isinstance(tree, cls):
             raise NotTreeError(filename)
         return tree
 
@@ -427,10 +793,16 @@
         return self._entries[name]
 
     def __setitem__(self, name, value):
-        assert isinstance(value, tuple)
-        assert len(value) == 2
+        """Set a tree entry by name.
+
+        :param name: The name of the entry, as a string.
+        :param value: A tuple of (mode, hexsha), where mode is the mode of the
+            entry as an integral type and hexsha is the hex SHA of the entry as
+            a string.
+        """
+        mode, hexsha = value
         self._ensure_parsed()
-        self._entries[name] = value
+        self._entries[name] = (mode, hexsha)
         self._needs_serialization = True
 
     def __delitem__(self, name):
@@ -442,153 +814,279 @@
         self._ensure_parsed()
         return len(self._entries)
 
+    def __iter__(self):
+        self._ensure_parsed()
+        return iter(self._entries)
+
     def add(self, mode, name, hexsha):
-        assert type(mode) == int
-        assert type(name) == str
-        assert type(hexsha) == str
+        """Add an entry to the tree.
+
+        :param mode: The mode of the entry as an integral type. Not all possible
+            modes are supported by git; see check() for details.
+        :param name: The name of the entry, as a string.
+        :param hexsha: The hex SHA of the entry as a string.
+        """
         self._ensure_parsed()
         self._entries[name] = mode, hexsha
         self._needs_serialization = True
 
     def entries(self):
-        """Return a list of tuples describing the tree entries"""
-        self._ensure_parsed()
-        # The order of this is different from iteritems() for historical reasons
-        return [(mode, name, hexsha) for (name, mode, hexsha) in self.iteritems()]
-
-    def iteritems(self):
-        def cmp_entry((name1, value1), (name2, value2)):
-            if stat.S_ISDIR(value1[0]):
-                name1 += "/"
-            if stat.S_ISDIR(value2[0]):
-                name2 += "/"
-            return cmp(name1, name2)
-        self._ensure_parsed()
-        for name, entry in sorted(self._entries.iteritems(), cmp=cmp_entry):
-            yield name, entry[0], entry[1]
-
-    def _parse_text(self):
+        """Return a list of tuples describing the tree entries.
+
+        :note: The order of the tuples that are returned is different from that
+            returned by the items and iteritems methods. This function will be
+            deprecated in the future.
+        """
+        self._ensure_parsed()
+        # The order of this is different from iteritems() for historical
+        # reasons
+        return [
+            (mode, name, hexsha) for (name, mode, hexsha) in self.iteritems()]
+
+    def iteritems(self, name_order=False):
+        """Iterate over entries.
+
+        :param name_order: If True, iterate in name order instead of tree order.
+        :return: Iterator over (name, mode, sha) tuples
+        """
+        self._ensure_parsed()
+        return sorted_tree_items(self._entries, name_order)
+
+    def items(self):
+        """Return the sorted entries in this tree.
+
+        :return: List with (name, mode, sha) tuples
+        """
+        return list(self.iteritems())
+
+    def _deserialize(self, chunks):
         """Grab the entries in the tree"""
-        self._entries = parse_tree(self._text)
-        self._needs_parsing = False
-
-    def serialize(self):
-        f = StringIO()
-        for name, mode, hexsha in self.iteritems():
-            f.write("%04o %s\0%s" % (mode, name, hex_to_sha(hexsha)))
-        self._text = f.getvalue()
-        self._needs_serialization = False
+        try:
+            parsed_entries = parse_tree("".join(chunks))
+        except ValueError, e:
+            raise ObjectFormatException(e)
+        # TODO: list comprehension is for efficiency in the common (small) case;
+        # if memory efficiency in the large case is a concern, use a genexp.
+        self._entries = dict([(n, (m, s)) for n, m, s in parsed_entries])
+
+    def check(self):
+        """Check this object for internal consistency.
+
+        :raise ObjectFormatException: if the object is malformed in some way
+        """
+        super(Tree, self).check()
+        last = None
+        allowed_modes = (stat.S_IFREG | 0755, stat.S_IFREG | 0644,
+                         stat.S_IFLNK, stat.S_IFDIR, S_IFGITLINK,
+                         # TODO: optionally exclude as in git fsck --strict
+                         stat.S_IFREG | 0664)
+        for name, mode, sha in parse_tree(''.join(self._chunked_text),
+                                          True):
+            check_hexsha(sha, 'invalid sha %s' % sha)
+            if '/' in name or name in ('', '.', '..'):
+                raise ObjectFormatException('invalid name %s' % name)
+
+            if mode not in allowed_modes:
+                raise ObjectFormatException('invalid mode %06o' % mode)
+
+            entry = (name, (mode, sha))
+            if last:
+                if cmp_entry(last, entry) > 0:
+                    raise ObjectFormatException('entries not sorted')
+                if name == last[0]:
+                    raise ObjectFormatException('duplicate entry %s' % name)
+            last = entry
+
+    def _serialize(self):
+        return list(serialize_tree(self.iteritems()))
 
     def as_pretty_string(self):
-        text = ""
+        text = []
         for name, mode, hexsha in self.iteritems():
             if mode & stat.S_IFDIR:
                 kind = "tree"
             else:
                 kind = "blob"
-            text += "%04o %s %s\t%s\n" % (mode, kind, hexsha, name)
-        return text
+            text.append("%04o %s %s\t%s\n" % (mode, kind, hexsha, name))
+        return "".join(text)
 
 
 def parse_timezone(text):
+    """Parse a timezone text fragment (e.g. '+0100').
+
+    :param text: Text to parse.
+    :return: Tuple with timezone as seconds difference to UTC
+        and a boolean indicating whether this was a UTC timezone
+        prefixed with a negative sign (-0000).
+    """
     offset = int(text)
+    negative_utc = (offset == 0 and text[0] == '-')
     signum = (offset < 0) and -1 or 1
     offset = abs(offset)
     hours = int(offset / 100)
     minutes = (offset % 100)
-    return signum * (hours * 3600 + minutes * 60)
-
-
-def format_timezone(offset):
+    return signum * (hours * 3600 + minutes * 60), negative_utc
+
+
+def format_timezone(offset, negative_utc=False):
+    """Format a timezone for Git serialization.
+
+    :param offset: Timezone offset as seconds difference to UTC
+    :param negative_utc: Whether to use a minus sign for UTC
+        (-0000 rather than +0000).
+    """
     if offset % 60 != 0:
         raise ValueError("Unable to handle non-minute offset.")
-    sign = (offset < 0) and '-' or '+'
+    if offset < 0 or (offset == 0 and negative_utc):
+        sign = '-'
+    else:
+        sign = '+'
     offset = abs(offset)
     return '%c%02d%02d' % (sign, offset / 3600, (offset / 60) % 60)
 
 
+def parse_commit(text):
+    return _parse_tag_or_commit(text)
+
+
 class Commit(ShaFile):
     """A git commit object"""
 
-    _type = COMMIT_ID
-    _num_type = 1
+    type_name = 'commit'
+    type_num = 1
+
+    __slots__ = ('_parents', '_encoding', '_extra', '_author_timezone_neg_utc',
+                 '_commit_timezone_neg_utc', '_commit_time',
+                 '_author_time', '_author_timezone', '_commit_timezone',
+                 '_author', '_committer', '_parents', '_extra',
+                 '_encoding', '_tree', '_message')
 
     def __init__(self):
         super(Commit, self).__init__()
         self._parents = []
         self._encoding = None
-        self._needs_parsing = False
-        self._needs_serialization = True
+        self._extra = {}
+        self._author_timezone_neg_utc = False
+        self._commit_timezone_neg_utc = False
 
     @classmethod
-    def from_file(cls, filename):
-        commit = ShaFile.from_file(filename)
-        if commit._type != cls._type:
-            raise NotCommitError(filename)
+    def from_path(cls, path):
+        commit = ShaFile.from_path(path)
+        if not isinstance(commit, cls):
+            raise NotCommitError(path)
         return commit
 
-    def _parse_text(self):
+    def _deserialize(self, chunks):
         self._parents = []
+        self._extra = []
         self._author = None
-        f = StringIO(self._text)
-        for l in f:
-            l = l.rstrip("\n")
-            if l == "":
-                # Empty line indicates end of headers
-                break
-            (field, value) = l.split(" ", 1)
-            if field == TREE_ID:
+        for field, value in parse_commit(''.join(self._chunked_text)):
+            if field == _TREE_HEADER:
                 self._tree = value
-            elif field == PARENT_ID:
+            elif field == _PARENT_HEADER:
                 self._parents.append(value)
-            elif field == AUTHOR_ID:
+            elif field == _AUTHOR_HEADER:
                 self._author, timetext, timezonetext = value.rsplit(" ", 2)
                 self._author_time = int(timetext)
-                self._author_timezone = parse_timezone(timezonetext)
-            elif field == COMMITTER_ID:
+                self._author_timezone, self._author_timezone_neg_utc =\
+                    parse_timezone(timezonetext)
+            elif field == _COMMITTER_HEADER:
                 self._committer, timetext, timezonetext = value.rsplit(" ", 2)
                 self._commit_time = int(timetext)
-                self._commit_timezone = parse_timezone(timezonetext)
-            elif field == ENCODING_ID:
+                self._commit_timezone, self._commit_timezone_neg_utc =\
+                    parse_timezone(timezonetext)
+            elif field == _ENCODING_HEADER:
                 self._encoding = value
+            elif field is None:
+                self._message = value
             else:
-                raise AssertionError("Unknown field %s" % field)
-        self._message = f.read()
-        self._needs_parsing = False
-
-    def serialize(self):
-        f = StringIO()
-        f.write("%s %s\n" % (TREE_ID, self._tree))
+                self._extra.append((field, value))
+
+    def check(self):
+        """Check this object for internal consistency.
+
+        :raise ObjectFormatException: if the object is malformed in some way
+        """
+        super(Commit, self).check()
+        self._check_has_member("_tree", "missing tree")
+        self._check_has_member("_author", "missing author")
+        self._check_has_member("_committer", "missing committer")
+        # times are currently checked when set
+
+        for parent in self._parents:
+            check_hexsha(parent, "invalid parent sha")
+        check_hexsha(self._tree, "invalid tree sha")
+
+        check_identity(self._author, "invalid author")
+        check_identity(self._committer, "invalid committer")
+
+        last = None
+        for field, _ in parse_commit("".join(self._chunked_text)):
+            if field == _TREE_HEADER and last is not None:
+                raise ObjectFormatException("unexpected tree")
+            elif field == _PARENT_HEADER and last not in (_PARENT_HEADER,
+                                                          _TREE_HEADER):
+                raise ObjectFormatException("unexpected parent")
+            elif field == _AUTHOR_HEADER and last not in (_TREE_HEADER,
+                                                          _PARENT_HEADER):
+                raise ObjectFormatException("unexpected author")
+            elif field == _COMMITTER_HEADER and last != _AUTHOR_HEADER:
+                raise ObjectFormatException("unexpected committer")
+            elif field == _ENCODING_HEADER and last != _COMMITTER_HEADER:
+                raise ObjectFormatException("unexpected encoding")
+            last = field
+
+        # TODO: optionally check for duplicate parents
+
+    def _serialize(self):
+        chunks = []
+        chunks.append("%s %s\n" % (_TREE_HEADER, self._tree))
         for p in self._parents:
-            f.write("%s %s\n" % (PARENT_ID, p))
-        f.write("%s %s %s %s\n" % (AUTHOR_ID, self._author, str(self._author_time), format_timezone(self._author_timezone)))
-        f.write("%s %s %s %s\n" % (COMMITTER_ID, self._committer, str(self._commit_time), format_timezone(self._commit_timezone)))
+            chunks.append("%s %s\n" % (_PARENT_HEADER, p))
+        chunks.append("%s %s %s %s\n" % (
+          _AUTHOR_HEADER, self._author, str(self._author_time),
+          format_timezone(self._author_timezone,
+                          self._author_timezone_neg_utc)))
+        chunks.append("%s %s %s %s\n" % (
+          _COMMITTER_HEADER, self._committer, str(self._commit_time),
+          format_timezone(self._commit_timezone,
+                          self._commit_timezone_neg_utc)))
         if self.encoding:
-            f.write("%s %s\n" % (ENCODING_ID, self.encoding))
-        f.write("\n") # There must be a new line after the headers
-        f.write(self._message)
-        self._text = f.getvalue()
-        self._needs_serialization = False
+            chunks.append("%s %s\n" % (_ENCODING_HEADER, self.encoding))
+        for k, v in self.extra:
+            if "\n" in k or "\n" in v:
+                raise AssertionError("newline in extra data: %r -> %r" % (k, v))
+            chunks.append("%s %s\n" % (k, v))
+        chunks.append("\n") # There must be a new line after the headers
+        chunks.append(self._message)
+        return chunks
 
     tree = serializable_property("tree", "Tree that is the state of this commit")
 
-    def get_parents(self):
+    def _get_parents(self):
         """Return a list of parents of this commit."""
         self._ensure_parsed()
         return self._parents
 
-    def set_parents(self, value):
-        """Return a list of parents of this commit."""
+    def _set_parents(self, value):
+        """Set a list of parents of this commit."""
         self._ensure_parsed()
         self._needs_serialization = True
         self._parents = value
 
-    parents = property(get_parents, set_parents)
-
-    author = serializable_property("author", 
+    parents = property(_get_parents, _set_parents)
+
+    def _get_extra(self):
+        """Return extra settings of this commit."""
+        self._ensure_parsed()
+        return self._extra
+
+    extra = property(_get_extra)
+
+    author = serializable_property("author",
         "The name of the author of the commit")
 
-    committer = serializable_property("committer", 
+    committer = serializable_property("committer",
         "The name of the committer of the commit")
 
     message = serializable_property("message",
@@ -600,35 +1098,36 @@
     commit_timezone = serializable_property("commit_timezone",
         "The zone the commit time is in")
 
-    author_time = serializable_property("author_time", 
+    author_time = serializable_property("author_time",
         "The timestamp the commit was written. as the number of seconds since the epoch.")
 
-    author_timezone = serializable_property("author_timezone", 
+    author_timezone = serializable_property("author_timezone",
         "Returns the zone the author time is in.")
 
     encoding = serializable_property("encoding",
         "Encoding of the commit message.")
 
 
-type_map = {
-    BLOB_ID : Blob,
-    TREE_ID : Tree,
-    COMMIT_ID : Commit,
-    TAG_ID: Tag,
-}
-
-num_type_map = {
-    0: None,
-    1: Commit,
-    2: Tree,
-    3: Blob,
-    4: Tag,
-    # 5 Is reserved for further expansion
-}
-
+OBJECT_CLASSES = (
+    Commit,
+    Tree,
+    Blob,
+    Tag,
+    )
+
+_TYPE_MAP = {}
+
+for cls in OBJECT_CLASSES:
+    _TYPE_MAP[cls.type_name] = cls
+    _TYPE_MAP[cls.type_num] = cls
+
+
+
+# Hold on to the pure-python implementations for testing
+_parse_tree_py = parse_tree
+_sorted_tree_items_py = sorted_tree_items
 try:
     # Try to import C versions
-    from dulwich._objects import parse_tree
+    from dulwich._objects import parse_tree, sorted_tree_items
 except ImportError:
     pass
-

=== modified file 'dulwich/pack.py'
--- dulwich/pack.py	2009-07-29 13:34:45 +0000
+++ dulwich/pack.py	2011-01-14 18:33:07 +0000
@@ -1,17 +1,17 @@
-# pack.py -- For dealing wih packed git objects.
+# pack.py -- For dealing with packed git objects.
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
-# Copryight (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
+#
 # 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) a later version.
-# 
+#
 # 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,
@@ -33,8 +33,14 @@
 try:
     from collections import defaultdict
 except ImportError:
-    from misc import defaultdict
+    from dulwich._compat import defaultdict
 
+from cStringIO import (
+    StringIO,
+    )
+from collections import (
+    deque,
+    )
 import difflib
 from itertools import (
     chain,
@@ -47,7 +53,7 @@
 try:
     from struct import unpack_from
 except ImportError:
-    from dulwich.misc import unpack_from
+    from dulwich._compat import unpack_from
 import sys
 import zlib
 
@@ -55,74 +61,79 @@
     ApplyDeltaError,
     ChecksumMismatch,
     )
+from dulwich.file import GitFile
 from dulwich.lru_cache import (
     LRUSizeCache,
     )
+from dulwich._compat import (
+    make_sha,
+    SEEK_END,
+    )
 from dulwich.objects import (
     ShaFile,
     hex_to_sha,
     sha_to_hex,
-    )
-from dulwich.misc import (
-    make_sha,
+    object_header,
     )
 
 supports_mmap_offset = (sys.version_info[0] >= 3 or
         (sys.version_info[0] == 2 and sys.version_info[1] >= 6))
 
 
-def take_msb_bytes(map, offset):
+OFS_DELTA = 6
+REF_DELTA = 7
+
+DELTA_TYPES = (OFS_DELTA, REF_DELTA)
+
+
+def take_msb_bytes(read):
     """Read bytes marked with most significant bit.
-    
-    :param map: The buffer.
-    :param offset: Offset in the buffer at which to start reading.
+
+    :param read: Read function
     """
     ret = []
     while len(ret) == 0 or ret[-1] & 0x80:
-        ret.append(ord(map[offset]))
-        offset += 1
+        ret.append(ord(read(1)))
     return ret
 
 
-def read_zlib_chunks(data, offset):
-    """Read chunks of zlib data from a buffer.
-    
-    :param data: Buffer to read from
-    :param offset: Offset at which to start reading
-    :return: Tuple with list of chunks and length of 
-        compressed data length
+def read_zlib_chunks(read_some, dec_size, buffer_size=4096):
+    """Read zlib data from a buffer.
+
+    This function requires that the buffer have additional data following the
+    compressed data, which is guaranteed to be the case for git pack files.
+
+    :param read_some: Read function that returns at least one byte, but may
+        return less than the requested size
+    :param dec_size: Expected size of the decompressed buffer
+    :param buffer_size: Size of the read buffer
+    :return: Tuple with list of chunks, length of compressed data length and
+        and unused read data.
+    :raise zlib.error: if a decompression error occurred.
     """
+    if dec_size <= -1:
+        raise ValueError("non-negative zlib data stream size expected")
     obj = zlib.decompressobj()
     ret = []
     fed = 0
+    size = 0
     while obj.unused_data == "":
-        base = offset+fed
-        add = data[base:base+1024]
-        if len(add) < 1024:
-            add += "Z"
+        add = read_some(buffer_size)
+        if not add:
+            raise zlib.error("EOF before end of zlib stream")
         fed += len(add)
-        ret.append(obj.decompress(add))
-    comp_len = fed-len(obj.unused_data)
-    return ret, comp_len
-
-
-def read_zlib(data, offset, dec_size):
-    """Read zlib-compressed data from a buffer.
-    
-    :param data: Buffer
-    :param offset: Offset in the buffer at which to read
-    :param dec_size: Size of the decompressed buffer
-    :return: Uncompressed buffer and compressed buffer length.
-    """
-    ret, comp_len = read_zlib_chunks(data, offset)
-    x = "".join(ret)
-    assert len(x) == dec_size
-    return x, comp_len
+        decomp = obj.decompress(add)
+        size += len(decomp)
+        ret.append(decomp)
+    if size != dec_size:
+        raise zlib.error("decompressed data does not match expected size")
+    comp_len = fed - len(obj.unused_data)
+    return ret, comp_len, obj.unused_data
 
 
 def iter_sha1(iter):
     """Return the hexdigest of the SHA1 over a set of names.
-    
+
     :param iter: Iterator over string objects
     :return: 40-byte hex sha1 digest
     """
@@ -132,40 +143,60 @@
     return sha1.hexdigest()
 
 
-def simple_mmap(f, offset, size, access=mmap.ACCESS_READ):
-    """Simple wrapper for mmap() which always supports the offset parameter.
-
-    :param f: File object.
-    :param offset: Offset in the file, from the beginning of the file.
-    :param size: Size of the mmap'ed area
-    :param access: Access mechanism.
-    :return: MMAP'd area.
-    """
-    mem = mmap.mmap(f.fileno(), size+offset, access=access)
-    return mem, offset
-
-
-def load_pack_index(filename):
+def load_pack_index(path):
     """Load an index file by path.
 
     :param filename: Path to the index file
-    """
-    f = open(filename, 'rb')
-    if f.read(4) == '\377tOc':
-        version = struct.unpack(">L", f.read(4))[0]
+    :return: A PackIndex loaded from the given path
+    """
+    f = GitFile(path, 'rb')
+    try:
+        return load_pack_index_file(path, f)
+    finally:
+        f.close()
+
+
+def _load_file_contents(f, size=None):
+    fileno = getattr(f, 'fileno', None)
+    # Attempt to use mmap if possible
+    if fileno is not None:
+        fd = f.fileno()
+        if size is None:
+            size = os.fstat(fd).st_size
+        try:
+            contents = mmap.mmap(fd, size, access=mmap.ACCESS_READ)
+        except mmap.error:
+            # Perhaps a socket?
+            pass
+        else:
+            return contents, size
+    contents = f.read()
+    size = len(contents)
+    return contents, size
+
+
+def load_pack_index_file(path, f):
+    """Load an index file from a file-like object.
+
+    :param path: Path for the index file
+    :param f: File-like object
+    :return: A PackIndex loaded from the given file
+    """
+    contents, size = _load_file_contents(f)
+    if contents[:4] == '\377tOc':
+        version = struct.unpack(">L", contents[4:8])[0]
         if version == 2:
-            f.seek(0)
-            return PackIndex2(filename, file=f)
+            return PackIndex2(path, file=f, contents=contents,
+                size=size)
         else:
             raise KeyError("Unknown pack index format %d" % version)
     else:
-        f.seek(0)
-        return PackIndex1(filename, file=f)
+        return PackIndex1(path, file=f, contents=contents, size=size)
 
 
 def bisect_find_sha(start, end, sha, unpack_name):
     """Find a SHA in a data blob with sorted SHAs.
-    
+
     :param start: Start index of range to search
     :param end: End index of range to search
     :param sha: Sha to find
@@ -188,10 +219,111 @@
 
 class PackIndex(object):
     """An index in to a packfile.
-  
+
     Given a sha id of an object a pack index can tell you the location in the
     packfile of that object if it has it.
-  
+    """
+
+    def __eq__(self, other):
+        if not isinstance(other, PackIndex):
+            return False
+
+        for (name1, _, _), (name2, _, _) in izip(self.iterentries(),
+                                                 other.iterentries()):
+            if name1 != name2:
+                return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __len__(self):
+        """Return the number of entries in this pack index."""
+        raise NotImplementedError(self.__len__)
+
+    def __iter__(self):
+        """Iterate over the SHAs in this pack."""
+        return imap(sha_to_hex, self._itersha())
+
+    def iterentries(self):
+        """Iterate over the entries in this pack index.
+
+        :return: iterator over tuples with object name, offset in packfile and
+            crc32 checksum.
+        """
+        raise NotImplementedError(self.iterentries)
+
+    def get_pack_checksum(self):
+        """Return the SHA1 checksum stored for the corresponding packfile.
+
+        :return: 20-byte binary digest
+        """
+        raise NotImplementedError(self.get_pack_checksum)
+
+    def object_index(self, sha):
+        """Return the index in to the corresponding packfile for the object.
+
+        Given the name of an object it will return the offset that object
+        lives at within the corresponding pack file. If the pack file doesn't
+        have the object then None will be returned.
+        """
+        if len(sha) == 40:
+            sha = hex_to_sha(sha)
+        return self._object_index(sha)
+
+    def _object_index(self, sha):
+        """See object_index.
+
+        :param sha: A *binary* SHA string. (20 characters long)_
+        """
+        raise NotImplementedError(self._object_index)
+
+    def objects_sha1(self):
+        """Return the hex SHA1 over all the shas of all objects in this pack.
+
+        :note: This is used for the filename of the pack.
+        """
+        return iter_sha1(self._itersha())
+
+    def _itersha(self):
+        """Yield all the SHA1's of the objects in the index, sorted."""
+        raise NotImplementedError(self._itersha)
+
+
+class MemoryPackIndex(PackIndex):
+    """Pack index that is stored entirely in memory."""
+
+    def __init__(self, entries, pack_checksum=None):
+        """Create a new MemoryPackIndex.
+
+        :param entries: Sequence of name, idx, crc32 (sorted)
+        :param pack_checksum: Optional pack checksum
+        """
+        self._by_sha = {}
+        for name, idx, crc32 in entries:
+            self._by_sha[name] = idx
+        self._entries = entries
+        self._pack_checksum = pack_checksum
+
+    def get_pack_checksum(self):
+        return self._pack_checksum
+
+    def __len__(self):
+        return len(self._entries)
+
+    def _object_index(self, sha):
+        return self._by_sha[sha][0]
+
+    def _itersha(self):
+        return iter(self._by_sha)
+
+    def iterentries(self):
+        return iter(self._entries)
+
+
+class FilePackIndex(PackIndex):
+    """Pack index that is based on a file.
+
     To do the loop it opens the file, and indexes first 256 4 byte groups
     with the first byte of the sha id. The value in the four byte group indexed
     is the end of the group that shares the same starting byte. Subtract one
@@ -199,57 +331,54 @@
     The values are sorted by sha id within the group, so do the math to find
     the start and end offset and then bisect in to find if the value is present.
     """
-  
-    def __init__(self, filename, file=None):
+
+    def __init__(self, filename, file=None, contents=None, size=None):
         """Create a pack index object.
-    
+
         Provide it with the name of the index file to consider, and it will map
         it whenever required.
         """
         self._filename = filename
         # Take the size now, so it can be checked each time we map the file to
         # ensure that it hasn't changed.
-        self._size = os.path.getsize(filename)
         if file is None:
-            self._file = open(filename, 'rb')
+            self._file = GitFile(filename, 'rb')
         else:
             self._file = file
-        self._contents, map_offset = simple_mmap(self._file, 0, self._size)
-        assert map_offset == 0
-  
+        if contents is None:
+            self._contents, self._size = _load_file_contents(self._file, size)
+        else:
+            self._contents, self._size = (contents, size)
+
     def __eq__(self, other):
-        if not isinstance(other, PackIndex):
-            return False
-    
-        if self._fan_out_table != other._fan_out_table:
-            return False
-    
-        for (name1, _, _), (name2, _, _) in izip(self.iterentries(), other.iterentries()):
-            if name1 != name2:
-                return False
-        return True
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-  
+        # Quick optimization:
+        if (isinstance(other, FilePackIndex) and
+            self._fan_out_table != other._fan_out_table):
+            return False
+
+        return super(FilePackIndex, self).__eq__(other)
+
     def close(self):
         self._file.close()
-  
+        if getattr(self._contents, "close", None) is not None:
+            self._contents.close()
+
     def __len__(self):
         """Return the number of entries in this pack index."""
         return self._fan_out_table[-1]
-  
+
     def _unpack_entry(self, i):
         """Unpack the i-th entry in the index file.
-    
-        :return: Tuple with object name (SHA), offset in pack file and 
-              CRC32 checksum (if known)."""
+
+        :return: Tuple with object name (SHA), offset in pack file and CRC32
+            checksum (if known).
+        """
         raise NotImplementedError(self._unpack_entry)
-  
+
     def _unpack_name(self, i):
         """Unpack the i-th name from the index file."""
         raise NotImplementedError(self._unpack_name)
-  
+
     def _unpack_offset(self, i):
         """Unpack the i-th object offset from the index file."""
         raise NotImplementedError(self._unpack_offset)
@@ -257,41 +386,34 @@
     def _unpack_crc32_checksum(self, i):
         """Unpack the crc32 checksum for the i-th object from the index file."""
         raise NotImplementedError(self._unpack_crc32_checksum)
-  
-    def __iter__(self):
-        """Iterate over the SHAs in this pack."""
-        return imap(sha_to_hex, self._itersha())
-  
+
     def _itersha(self):
         for i in range(len(self)):
             yield self._unpack_name(i)
-  
-    def objects_sha1(self):
-        """Return the hex SHA1 over all the shas of all objects in this pack.
-        
-        :note: This is used for the filename of the pack.
-        """
-        return iter_sha1(self._itersha())
-  
+
     def iterentries(self):
         """Iterate over the entries in this pack index.
-       
-        Will yield tuples with object name, offset in packfile and crc32 checksum.
+
+        :return: iterator over tuples with object name, offset in packfile and
+            crc32 checksum.
         """
         for i in range(len(self)):
             yield self._unpack_entry(i)
-  
+
     def _read_fan_out_table(self, start_offset):
         ret = []
         for i in range(0x100):
-            ret.append(struct.unpack(">L", self._contents[start_offset+i*4:start_offset+(i+1)*4])[0])
+            fanout_entry = self._contents[start_offset+i*4:start_offset+(i+1)*4]
+            ret.append(struct.unpack(">L", fanout_entry)[0])
         return ret
-  
+
     def check(self):
         """Check that the stored checksum matches the actual checksum."""
-        # TODO: Check pack contents, too
-        return self.calculate_checksum() == self.get_stored_checksum()
-  
+        actual = self.calculate_checksum()
+        stored = self.get_stored_checksum()
+        if actual != stored:
+            raise ChecksumMismatch(stored, actual)
+
     def calculate_checksum(self):
         """Calculate the SHA1 checksum over this pack index.
 
@@ -301,32 +423,21 @@
 
     def get_pack_checksum(self):
         """Return the SHA1 checksum stored for the corresponding packfile.
-        
+
         :return: 20-byte binary digest
         """
         return str(self._contents[-40:-20])
-  
+
     def get_stored_checksum(self):
         """Return the SHA1 checksum stored for this index.
-        
+
         :return: 20-byte binary digest
         """
         return str(self._contents[-20:])
-  
-    def object_index(self, sha):
-        """Return the index in to the corresponding packfile for the object.
-    
-        Given the name of an object it will return the offset that object lives
-        at within the corresponding pack file. If the pack file doesn't have the
-        object then None will be returned.
-        """
-        if len(sha) == 40:
-            sha = hex_to_sha(sha)
-        return self._object_index(sha)
-  
+
     def _object_index(self, sha):
         """See object_index.
-        
+
         :param sha: A *binary* SHA string. (20 characters long)_
         """
         assert len(sha) == 20
@@ -340,72 +451,72 @@
         if i is None:
             raise KeyError(sha)
         return self._unpack_offset(i)
-            
-
-
-class PackIndex1(PackIndex):
-    """Version 1 Pack Index."""
-
-    def __init__(self, filename, file=None):
-        PackIndex.__init__(self, filename, file)
+
+
+class PackIndex1(FilePackIndex):
+    """Version 1 Pack Index file."""
+
+    def __init__(self, filename, file=None, contents=None, size=None):
+        super(PackIndex1, self).__init__(filename, file, contents, size)
         self.version = 1
         self._fan_out_table = self._read_fan_out_table(0)
 
     def _unpack_entry(self, i):
-        (offset, name) = unpack_from(">L20s", self._contents, 
-            (0x100 * 4) + (i * 24))
+        (offset, name) = unpack_from(">L20s", self._contents,
+                                     (0x100 * 4) + (i * 24))
         return (name, offset, None)
- 
+
     def _unpack_name(self, i):
         offset = (0x100 * 4) + (i * 24) + 4
         return self._contents[offset:offset+20]
-  
+
     def _unpack_offset(self, i):
         offset = (0x100 * 4) + (i * 24)
         return unpack_from(">L", self._contents, offset)[0]
-  
+
     def _unpack_crc32_checksum(self, i):
         # Not stored in v1 index files
-        return None 
-  
-
-class PackIndex2(PackIndex):
-    """Version 2 Pack Index."""
-
-    def __init__(self, filename, file=None):
-        PackIndex.__init__(self, filename, file)
+        return None
+
+
+class PackIndex2(FilePackIndex):
+    """Version 2 Pack Index file."""
+
+    def __init__(self, filename, file=None, contents=None, size=None):
+        super(PackIndex2, self).__init__(filename, file, contents, size)
         assert self._contents[:4] == '\377tOc', "Not a v2 pack index file"
         (self.version, ) = unpack_from(">L", self._contents, 4)
         assert self.version == 2, "Version was %d" % self.version
         self._fan_out_table = self._read_fan_out_table(8)
         self._name_table_offset = 8 + 0x100 * 4
         self._crc32_table_offset = self._name_table_offset + 20 * len(self)
-        self._pack_offset_table_offset = self._crc32_table_offset + 4 * len(self)
+        self._pack_offset_table_offset = (self._crc32_table_offset +
+                                          4 * len(self))
 
     def _unpack_entry(self, i):
-        return (self._unpack_name(i), self._unpack_offset(i), 
+        return (self._unpack_name(i), self._unpack_offset(i),
                 self._unpack_crc32_checksum(i))
- 
+
     def _unpack_name(self, i):
         offset = self._name_table_offset + i * 20
         return self._contents[offset:offset+20]
-  
+
     def _unpack_offset(self, i):
         offset = self._pack_offset_table_offset + i * 4
         return unpack_from(">L", self._contents, offset)[0]
-  
+
     def _unpack_crc32_checksum(self, i):
-        return unpack_from(">L", self._contents, 
+        return unpack_from(">L", self._contents,
                           self._crc32_table_offset + i * 4)[0]
-  
-
-
-def read_pack_header(f):
+
+
+def read_pack_header(read):
     """Read the header of a pack file.
 
-    :param f: File-like object to read from
+    :param read: Read function
+    :return: Tuple with pack version and number of objects
     """
-    header = f.read(12)
+    header = read(12)
     assert header[:4] == "PACK"
     (version,) = unpack_from(">L", header, 4)
     assert version in (2, 3), "Version was %d" % version
@@ -413,291 +524,425 @@
     return (version, num_objects)
 
 
-def unpack_object(map, offset=0):
+def chunks_length(chunks):
+    return sum(imap(len, chunks))
+
+
+def unpack_object(read_all, read_some=None):
     """Unpack a Git object.
 
-    :return: tuple with type, uncompressed data and compressed size
+    :param read_all: Read function that blocks until the number of requested
+        bytes are read.
+    :param read_some: Read function that returns at least one byte, but may not
+        return the number of bytes requested.
+    :return: tuple with type, uncompressed data, compressed size and tail data.
     """
-    bytes = take_msb_bytes(map, offset)
+    if read_some is None:
+        read_some = read_all
+    bytes = take_msb_bytes(read_all)
     type = (bytes[0] >> 4) & 0x07
     size = bytes[0] & 0x0f
     for i, byte in enumerate(bytes[1:]):
         size += (byte & 0x7f) << ((i * 7) + 4)
     raw_base = len(bytes)
-    if type == 6: # offset delta
-        bytes = take_msb_bytes(map, raw_base + offset)
+    if type == OFS_DELTA:
+        bytes = take_msb_bytes(read_all)
+        raw_base += len(bytes)
         assert not (bytes[-1] & 0x80)
         delta_base_offset = bytes[0] & 0x7f
         for byte in bytes[1:]:
             delta_base_offset += 1
             delta_base_offset <<= 7
             delta_base_offset += (byte & 0x7f)
-        raw_base+=len(bytes)
-        uncomp, comp_len = read_zlib(map, offset + raw_base, size)
-        assert size == len(uncomp)
-        return type, (delta_base_offset, uncomp), comp_len+raw_base
-    elif type == 7: # ref delta
-        basename = map[offset+raw_base:offset+raw_base+20]
-        uncomp, comp_len = read_zlib(map, offset+raw_base+20, size)
-        assert size == len(uncomp)
-        return type, (basename, uncomp), comp_len+raw_base+20
+        uncomp, comp_len, unused = read_zlib_chunks(read_some, size)
+        assert size == chunks_length(uncomp)
+        return type, (delta_base_offset, uncomp), comp_len+raw_base, unused
+    elif type == REF_DELTA:
+        basename = read_all(20)
+        raw_base += 20
+        uncomp, comp_len, unused = read_zlib_chunks(read_some, size)
+        assert size == chunks_length(uncomp)
+        return type, (basename, uncomp), comp_len+raw_base, unused
     else:
-        uncomp, comp_len = read_zlib(map, offset+raw_base, size)
-        assert len(uncomp) == size
-        return type, uncomp, comp_len+raw_base
+        uncomp, comp_len, unused = read_zlib_chunks(read_some, size)
+        assert chunks_length(uncomp) == size
+        return type, uncomp, comp_len+raw_base, unused
 
 
 def _compute_object_size((num, obj)):
-    """Compute the size of a unresolved object for use with LRUSizeCache.
+    """Compute the size of a unresolved object for use with LRUSizeCache."""
+    if num in DELTA_TYPES:
+        return chunks_length(obj[1])
+    return chunks_length(obj)
+
+
+class PackStreamReader(object):
+    """Class to read a pack stream.
+
+    The pack is read from a ReceivableProtocol using read() or recv() as
+    appropriate.
     """
-    if num in (6, 7):
-        return len(obj[1])
-    assert isinstance(obj, str)
-    return len(obj)
+
+    def __init__(self, read_all, read_some=None):
+        self.read_all = read_all
+        if read_some is None:
+            self.read_some = read_all
+        else:
+            self.read_some = read_some
+        self.sha = make_sha()
+        self._offset = 0
+        self._rbuf = StringIO()
+        # trailer is a deque to avoid memory allocation on small reads
+        self._trailer = deque()
+
+    def _read(self, read, size):
+        """Read up to size bytes using the given callback.
+
+        As a side effect, update the verifier's hash (excluding the last 20
+        bytes read) and write through to the output file.
+
+        :param read: The read callback to read from.
+        :param size: The maximum number of bytes to read; the particular
+            behavior is callback-specific.
+        """
+        data = read(size)
+
+        # maintain a trailer of the last 20 bytes we've read
+        n = len(data)
+        self._offset += n
+        tn = len(self._trailer)
+        if n >= 20:
+            to_pop = tn
+            to_add = 20
+        else:
+            to_pop = max(n + tn - 20, 0)
+            to_add = n
+        for _ in xrange(to_pop):
+            self.sha.update(self._trailer.popleft())
+        self._trailer.extend(data[-to_add:])
+
+        # hash everything but the trailer
+        self.sha.update(data[:-to_add])
+        return data
+
+    def _buf_len(self):
+        buf = self._rbuf
+        start = buf.tell()
+        buf.seek(0, SEEK_END)
+        end = buf.tell()
+        buf.seek(start)
+        return end - start
+
+    @property
+    def offset(self):
+        return self._offset - self._buf_len()
+
+    def read(self, size):
+        """Read, blocking until size bytes are read."""
+        buf_len = self._buf_len()
+        if buf_len >= size:
+            return self._rbuf.read(size)
+        buf_data = self._rbuf.read()
+        self._rbuf = StringIO()
+        return buf_data + self._read(self.read_all, size - buf_len)
+
+    def recv(self, size):
+        """Read up to size bytes, blocking until one byte is read."""
+        buf_len = self._buf_len()
+        if buf_len:
+            data = self._rbuf.read(size)
+            if size >= buf_len:
+                self._rbuf = StringIO()
+            return data
+        return self._read(self.read_some, size)
+
+    def __len__(self):
+        return self._num_objects
+
+    def read_objects(self):
+        """Read the objects in this pack file.
+
+        :raise AssertionError: if there is an error in the pack format.
+        :raise ChecksumMismatch: if the checksum of the pack contents does not
+            match the checksum in the pack trailer.
+        :raise zlib.error: if an error occurred during zlib decompression.
+        :raise IOError: if an error occurred writing to the output file.
+        """
+        pack_version, self._num_objects = read_pack_header(self.read)
+        for i in xrange(self._num_objects):
+            type, uncomp, comp_len, unused = unpack_object(self.read, self.recv)
+            yield type, uncomp, comp_len
+
+            # prepend any unused data to current read buffer
+            buf = StringIO()
+            buf.write(unused)
+            buf.write(self._rbuf.read())
+            buf.seek(0)
+            self._rbuf = buf
+
+        pack_sha = sha_to_hex(''.join([c for c in self._trailer]))
+        calculated_sha = self.sha.hexdigest()
+        if pack_sha != calculated_sha:
+            raise ChecksumMismatch(pack_sha, calculated_sha)
+
+
+class PackObjectIterator(object):
+
+    def __init__(self, pack, progress=None):
+        self.i = 0
+        self.offset = pack._header_size
+        self.num = len(pack)
+        self.map = pack._file
+        self._progress = progress
+
+    def __iter__(self):
+        return self
+
+    def __len__(self):
+        return self.num
+
+    def next(self):
+        if self.i == self.num:
+            raise StopIteration
+        self.map.seek(self.offset)
+        (type, obj, total_size, unused) = unpack_object(self.map.read)
+        self.map.seek(self.offset)
+        crc32 = zlib.crc32(self.map.read(total_size)) & 0xffffffff
+        ret = (self.offset, type, obj, crc32)
+        self.offset += total_size
+        if self._progress is not None:
+            self._progress(self.i, self.num)
+        self.i+=1
+        return ret
+
+def obj_sha(type, chunks):
+    """Compute the SHA for a numeric type and object chunks."""
+    sha = make_sha()
+    sha.update(object_header(type, chunks_length(chunks)))
+    for chunk in chunks:
+        sha.update(chunk)
+    return sha.digest()
 
 
 class PackData(object):
     """The data contained in a packfile.
-  
+
     Pack files can be accessed both sequentially for exploding a pack, and
     directly with the help of an index to retrieve a specific object.
-  
+
     The objects within are either complete or a delta aginst another.
-  
+
     The header is variable length. If the MSB of each byte is set then it
     indicates that the subsequent byte is still part of the header.
     For the first byte the next MS bits are the type, which tells you the type
     of object, and whether it is a delta. The LS byte is the lowest bits of the
     size. For each subsequent byte the LS 7 bits are the next MS bits of the
     size, i.e. the last byte of the header contains the MS bits of the size.
-  
+
     For the complete objects the data is stored as zlib deflated data.
     The size in the header is the uncompressed object size, so to uncompress
     you need to just keep feeding data to zlib until you get an object back,
     or it errors on bad data. This is done here by just giving the complete
     buffer from the start of the deflated object on. This is bad, but until I
     get mmap sorted out it will have to do.
-  
-    Currently there are no integrity checks done. Also no attempt is made to try
-    and detect the delta case, or a request for an object at the wrong position.
-    It will all just throw a zlib or KeyError.
+
+    Currently there are no integrity checks done. Also no attempt is made to
+    try and detect the delta case, or a request for an object at the wrong
+    position.  It will all just throw a zlib or KeyError.
     """
-  
-    def __init__(self, filename):
-        """Create a PackData object that represents the pack in the given filename.
-    
+
+    def __init__(self, filename, file=None, size=None):
+        """Create a PackData object representing the pack in the given filename.
+
         The file must exist and stay readable until the object is disposed of. It
         must also stay the same size. It will be mapped whenever needed.
-    
+
         Currently there is a restriction on the size of the pack as the python
         mmap implementation is flawed.
         """
         self._filename = filename
-        assert os.path.exists(filename), "%s is not a packfile" % filename
-        self._size = os.path.getsize(filename)
+        self._size = size
         self._header_size = 12
-        assert self._size >= self._header_size, "%s is too small for a packfile (%d < %d)" % (filename, self._size, self._header_size)
-        self._file = open(self._filename, 'rb')
-        self._read_header()
-        self._offset_cache = LRUSizeCache(1024*1024*20, 
+        if file is None:
+            self._file = GitFile(self._filename, 'rb')
+        else:
+            self._file = file
+        (version, self._num_objects) = read_pack_header(self._file.read)
+        self._offset_cache = LRUSizeCache(1024*1024*20,
             compute_size=_compute_object_size)
+        self.pack = None
+
+    @classmethod
+    def from_file(cls, file, size):
+        return cls(str(file), file=file, size=size)
+
+    @classmethod
+    def from_path(cls, path):
+        return cls(filename=path)
 
     def close(self):
         self._file.close()
-  
-    def _read_header(self):
-        (version, self._num_objects) = read_pack_header(self._file)
-        self._file.seek(self._size-20)
-        self._stored_checksum = self._file.read(20)
-  
+
+    def _get_size(self):
+        if self._size is not None:
+            return self._size
+        self._size = os.path.getsize(self._filename)
+        if self._size < self._header_size:
+            errmsg = ("%s is too small for a packfile (%d < %d)" %
+                      (self._filename, self._size, self._header_size))
+            raise AssertionError(errmsg)
+        return self._size
+
     def __len__(self):
         """Returns the number of objects in this pack."""
         return self._num_objects
-  
+
     def calculate_checksum(self):
         """Calculate the checksum for this pack.
 
         :return: 20-byte binary SHA1 digest
         """
-        map, map_offset = simple_mmap(self._file, 0, self._size - 20)
-        try:
-            return make_sha(map[map_offset:self._size-20]).digest()
-        finally:
-            map.close()
-
-    def resolve_object(self, offset, type, obj, get_ref, get_offset=None):
+        s = make_sha()
+        self._file.seek(0)
+        todo = self._get_size() - 20
+        while todo > 0:
+            x = self._file.read(min(todo, 1<<16))
+            s.update(x)
+            todo -= len(x)
+        return s.digest()
+
+    def get_ref(self, sha):
+        """Get the object for a ref SHA, only looking in this pack."""
+        # TODO: cache these results
+        if self.pack is None:
+            raise KeyError(sha)
+        offset = self.pack.index.object_index(sha)
+        if not offset:
+            raise KeyError(sha)
+        type, obj = self.get_object_at(offset)
+        return offset, type, obj
+
+    def resolve_object(self, offset, type, obj, get_ref=None):
         """Resolve an object, possibly resolving deltas when necessary.
-        
+
         :return: Tuple with object type and contents.
         """
-        if type not in (6, 7): # Not a delta
+        if type not in DELTA_TYPES:
             return type, obj
 
-        if get_offset is None:
-            get_offset = self.get_object_at
-      
-        if type == 6: # offset delta
+        if get_ref is None:
+            get_ref = self.get_ref
+        if type == OFS_DELTA:
             (delta_offset, delta) = obj
+            # TODO: clean up asserts and replace with nicer error messages
+            assert isinstance(offset, int)
             assert isinstance(delta_offset, int)
-            assert isinstance(delta, str)
             base_offset = offset-delta_offset
-            type, base_obj = get_offset(base_offset)
+            type, base_obj = self.get_object_at(base_offset)
             assert isinstance(type, int)
-        elif type == 7: # ref delta
+        elif type == REF_DELTA:
             (basename, delta) = obj
             assert isinstance(basename, str) and len(basename) == 20
-            assert isinstance(delta, str)
-            type, base_obj = get_ref(basename)
+            base_offset, type, base_obj = get_ref(basename)
             assert isinstance(type, int)
-            # Can't be a ofs delta, as we wouldn't know the base offset
-            assert type != 6
-            base_offset = None
-        type, base_text = self.resolve_object(base_offset, type, base_obj, get_ref)
-        if base_offset is not None:
-            self._offset_cache[base_offset] = type, base_text
-        ret = (type, apply_delta(base_text, delta))
-        return ret
-  
+        type, base_chunks = self.resolve_object(base_offset, type, base_obj)
+        chunks = apply_delta(base_chunks, delta)
+        # TODO(dborowitz): This can result in poor performance if large base
+        # objects are separated from deltas in the pack. We should reorganize
+        # so that we apply deltas to all objects in a chain one after the other
+        # to optimize cache performance.
+        if offset is not None:
+            self._offset_cache[offset] = type, chunks
+        return type, chunks
+
     def iterobjects(self, progress=None):
-
-        class ObjectIterator(object):
-            
-            def __init__(self, pack):
-                self.i = 0
-                self.offset = pack._header_size
-                self.num = len(pack)
-                self.map, _ = simple_mmap(pack._file, 0, pack._size)
-
-            def __del__(self):
-                self.map.close()
-
-            def __iter__(self):
-                return self
-
-            def __len__(self):
-                return self.num
-            
-            def next(self):
-                if self.i == self.num:
-                    raise StopIteration
-                (type, obj, total_size) = unpack_object(self.map, self.offset)
-                crc32 = zlib.crc32(self.map[self.offset:self.offset+total_size]) & 0xffffffff
-                ret = (self.offset, type, obj, crc32)
-                self.offset += total_size
-                if progress:
-                    progress(self.i, self.num)
-                self.i+=1
-                return ret
-        return ObjectIterator(self)
-  
-    def iterentries(self, ext_resolve_ref=None, progress=None):
+        return PackObjectIterator(self, progress)
+
+    def iterentries(self, progress=None):
         """Yield entries summarizing the contents of this pack.
 
-        :param ext_resolve_ref: Optional function to resolve base
-            objects (in case this is a thin pack)
-        :param progress: Progress function, called with current and
-            total object count.
-
-        This will yield tuples with (sha, offset, crc32)
+        :param progress: Progress function, called with current and total
+            object count.
+        :return: iterator of tuples with (sha, offset, crc32)
         """
-        found = {}
-        postponed = defaultdict(list)
-        class Postpone(Exception):
-            """Raised to postpone delta resolving."""
-          
-        def get_ref_text(sha):
-            assert len(sha) == 20
-            if sha in found:
-                return self.get_object_at(found[sha])
-            if ext_resolve_ref:
-                try:
-                    return ext_resolve_ref(sha)
-                except KeyError:
-                    pass
-            raise Postpone, (sha, )
-        extra = []
-        todo = chain(self.iterobjects(progress=progress), extra)
-        for (offset, type, obj, crc32) in todo:
+        for offset, type, obj, crc32 in self.iterobjects(progress=progress):
             assert isinstance(offset, int)
             assert isinstance(type, int)
-            assert isinstance(obj, tuple) or isinstance(obj, str)
-            try:
-                type, obj = self.resolve_object(offset, type, obj, get_ref_text)
-            except Postpone, (sha, ):
-                postponed[sha].append((offset, type, obj))
-            else:
-                shafile = ShaFile.from_raw_string(type, obj)
-                sha = shafile.sha().digest()
-                found[sha] = offset
-                yield sha, offset, crc32
-                extra.extend(postponed.get(sha, []))
-        if postponed:
-            raise KeyError([sha_to_hex(h) for h in postponed.keys()])
-  
-    def sorted_entries(self, resolve_ext_ref=None, progress=None):
+            assert isinstance(obj, list) or isinstance(obj, tuple)
+            type, obj = self.resolve_object(offset, type, obj)
+            yield obj_sha(type, obj), offset, crc32
+
+    def sorted_entries(self, progress=None):
         """Return entries in this pack, sorted by SHA.
 
-        :param ext_resolve_ref: Optional function to resolve base
-            objects (in case this is a thin pack)
-        :param progress: Progress function, called with current and
-            total object count.
+        :param progress: Progress function, called with current and total
+            object count
         :return: List of tuples with (sha, offset, crc32)
         """
-        ret = list(self.iterentries(resolve_ext_ref, progress=progress))
+        ret = list(self.iterentries(progress=progress))
         ret.sort()
         return ret
-  
-    def create_index_v1(self, filename, resolve_ext_ref=None, progress=None):
+
+    def create_index_v1(self, filename, progress=None):
         """Create a version 1 file for this data file.
 
         :param filename: Index filename.
-        :param resolve_ext_ref: Function to use for resolving externally referenced
-            SHA1s (for thin packs)
         :param progress: Progress report function
+        :return: Checksum of index file
         """
-        entries = self.sorted_entries(resolve_ext_ref, progress=progress)
-        write_pack_index_v1(filename, entries, self.calculate_checksum())
-  
-    def create_index_v2(self, filename, resolve_ext_ref=None, progress=None):
+        entries = self.sorted_entries(progress=progress)
+        f = GitFile(filename, 'wb')
+        try:
+            return write_pack_index_v1(f, entries, self.calculate_checksum())
+        finally:
+            f.close()
+
+    def create_index_v2(self, filename, progress=None):
         """Create a version 2 index file for this data file.
 
         :param filename: Index filename.
-        :param resolve_ext_ref: Function to use for resolving externally referenced
-            SHA1s (for thin packs)
         :param progress: Progress report function
+        :return: Checksum of index file
         """
-        entries = self.sorted_entries(resolve_ext_ref, progress=progress)
-        write_pack_index_v2(filename, entries, self.calculate_checksum())
+        entries = self.sorted_entries(progress=progress)
+        f = GitFile(filename, 'wb')
+        try:
+            return write_pack_index_v2(f, entries, self.calculate_checksum())
+        finally:
+            f.close()
 
-    def create_index(self, filename, resolve_ext_ref=None, progress=None,
+    def create_index(self, filename, progress=None,
                      version=2):
         """Create an  index file for this data file.
 
         :param filename: Index filename.
-        :param resolve_ext_ref: Function to use for resolving externally referenced
-            SHA1s (for thin packs)
         :param progress: Progress report function
+        :return: Checksum of index file
         """
         if version == 1:
-            self.create_index_v1(filename, resolve_ext_ref, progress)
+            return self.create_index_v1(filename, progress)
         elif version == 2:
-            self.create_index_v2(filename, resolve_ext_ref, progress)
+            return self.create_index_v2(filename, progress)
         else:
             raise ValueError("unknown index format %d" % version)
-  
+
     def get_stored_checksum(self):
         """Return the expected checksum stored in this pack."""
-        return self._stored_checksum
-  
+        self._file.seek(self._get_size()-20)
+        return self._file.read(20)
+
     def check(self):
         """Check the consistency of this pack."""
-        return (self.calculate_checksum() == self.get_stored_checksum())
-  
+        actual = self.calculate_checksum()
+        stored = self.get_stored_checksum()
+        if actual != stored:
+            raise ChecksumMismatch(stored, actual)
+
     def get_object_at(self, offset):
         """Given an offset in to the packfile return the object that is there.
-    
-        Using the associated index the location of an object can be looked up, and
-        then the packfile can be asked directly for that object using this
+
+        Using the associated index the location of an object can be looked up,
+        and then the packfile can be asked directly for that object using this
         function.
         """
         if offset in self._offset_cache:
@@ -705,17 +950,87 @@
         assert isinstance(offset, long) or isinstance(offset, int),\
                 "offset was %r" % offset
         assert offset >= self._header_size
-        map, map_offset = simple_mmap(self._file, offset, self._size-offset)
+        self._file.seek(offset)
+        return unpack_object(self._file.read)[:2]
+
+
+class ThinPackData(PackData):
+    """PackData for thin packs, which require an ObjectStore for resolving."""
+
+    def __init__(self, resolve_ext_ref, *args, **kwargs):
+        super(ThinPackData, self).__init__(*args, **kwargs)
+        self.resolve_ext_ref = resolve_ext_ref
+
+    @classmethod
+    def from_file(cls, resolve_ext_ref, file, size):
+        return cls(resolve_ext_ref, str(file), file=file, size=size)
+
+    def get_ref(self, sha):
+        """Resolve a reference looking in both this pack and the store."""
         try:
-            ret = unpack_object(map, map_offset)[:2]
-            return ret
-        finally:
-            map.close()
+            # As part of completing a pack we create a Pack object with a
+            # ThinPackData and a full PackIndex, so check in the index first if
+            # possible.
+            # TODO(dborowitz): reevaluate this when the pack completion code is
+            # rewritten.
+            return super(ThinPackData, self).get_ref(sha)
+        except KeyError:
+            type, obj = self.resolve_ext_ref(sha)
+            return None, type, obj
+
+    def iterentries(self, progress=None):
+        """Yield entries summarizing the contents of this pack.
+
+        :param progress: Progress function, called with current and
+            total object count.
+
+        This will yield tuples with (sha, offset, crc32)
+        """
+        found = {}
+        postponed = defaultdict(list)
+
+        class Postpone(Exception):
+            """Raised to postpone delta resolving."""
+
+            def __init__(self, sha):
+                self.sha = sha
+
+        def get_ref_text(sha):
+            assert len(sha) == 20
+            if sha in found:
+                offset = found[sha]
+                type, obj = self.get_object_at(offset)
+                return offset, type, obj
+            try:
+                return self.get_ref(sha)
+            except KeyError:
+                raise Postpone(sha)
+
+        extra = []
+        todo = chain(self.iterobjects(progress=progress), extra)
+        for (offset, type, obj, crc32) in todo:
+            assert isinstance(offset, int)
+            if obj is None:
+                # Inflate postponed delta
+                obj, type = self.get_object_at(offset)
+            assert isinstance(type, int)
+            assert isinstance(obj, list) or isinstance(obj, tuple)
+            try:
+                type, obj = self.resolve_object(offset, type, obj, get_ref_text)
+            except Postpone, e:
+                # Save memory by not storing the inflated obj in postponed
+                postponed[e.sha].append((offset, type, None, crc32))
+            else:
+                sha = obj_sha(type, obj)
+                found[sha] = offset
+                yield sha, offset, crc32
+                extra.extend(postponed.pop(sha, []))
+        if postponed:
+            raise KeyError([sha_to_hex(h) for h in postponed.keys()])
 
 
 class SHA1Reader(object):
-    """Wrapper around a file-like object that remembers the SHA1 of 
-    the data read from it."""
+    """Wrapper around a file-like object that remembers the SHA1 of its data."""
 
     def __init__(self, f):
         self.f = f
@@ -739,9 +1054,8 @@
 
 
 class SHA1Writer(object):
-    """Wrapper around a file-like object that remembers the SHA1 of 
-    the data written to it."""
-    
+    """Wrapper around a file-like object that remembers the SHA1 of its data."""
+
     def __init__(self, f):
         self.f = f
         self.sha1 = make_sha("")
@@ -769,14 +1083,15 @@
     """Write pack object to a file.
 
     :param f: File to write to
-    :param o: Object to write
+    :param type: Numeric type of the object
+    :param object: Object to write
     :return: Tuple with offset at which the object was written, and crc32
     """
     offset = f.tell()
     packed_data_hdr = ""
-    if type == 6: # offset delta
+    if type == OFS_DELTA:
         (delta_base_offset, object) = object
-    elif type == 7: # ref delta
+    elif type == REF_DELTA:
         (basename, object) = object
     size = len(object)
     c = (type << 4) | (size & 15)
@@ -786,7 +1101,7 @@
         c = size & 0x7f
         size >>= 7
     packed_data_hdr += chr(c)
-    if type == 6: # offset delta
+    if type == OFS_DELTA:
         ret = [delta_base_offset & 0x7f]
         delta_base_offset >>= 7
         while delta_base_offset:
@@ -794,7 +1109,7 @@
             ret.insert(0, 0x80 | (delta_base_offset & 0x7f))
             delta_base_offset >>= 7
         packed_data_hdr += "".join([chr(x) for x in ret])
-    elif type == 7: # ref delta
+    elif type == REF_DELTA:
         assert len(basename) == 20
         packed_data_hdr += basename
     packed_data = packed_data_hdr + zlib.compress(object)
@@ -808,21 +1123,36 @@
     :param filename: Path to the new pack file (without .pack extension)
     :param objects: Iterable over (object, path) tuples to write
     :param num_objects: Number of objects to write
+    :return: Tuple with checksum of pack file and index file
     """
-    f = open(filename + ".pack", 'wb')
+    f = GitFile(filename + ".pack", 'wb')
     try:
         entries, data_sum = write_pack_data(f, objects, num_objects)
     finally:
         f.close()
     entries.sort()
-    write_pack_index_v2(filename + ".idx", entries, data_sum)
+    f = GitFile(filename + ".idx", 'wb')
+    try:
+        return data_sum, write_pack_index_v2(f, entries, data_sum)
+    finally:
+        f.close()
+
+
+def write_pack_header(f, num_objects):
+    """Write a pack header for the given number of objects."""
+    f.write('PACK')                          # Pack header
+    f.write(struct.pack('>L', 2))            # Pack version
+    f.write(struct.pack('>L', num_objects))  # Number of objects in pack
 
 
 def write_pack_data(f, objects, num_objects, window=10):
-    """Write a new pack file.
+    """Write a new pack data file.
 
-    :param filename: The filename of the new pack file.
-    :param objects: List of objects to write (tuples with object and path)
+    :param f: File to write to
+    :param objects: Iterable over (object, path) tuples to write
+    :param num_objects: Number of objects to write
+    :param window: Sliding window size for searching for deltas; currently
+                   unimplemented
     :return: List with (name, offset, crc32 checksum) entries, pack checksum
     """
     recency = list(objects)
@@ -832,29 +1162,27 @@
     # This helps us find good objects to diff against us
     magic = []
     for obj, path in recency:
-        magic.append( (obj.type, path, 1, -len(obj.as_raw_string()), obj) )
+        magic.append( (obj.type_num, path, 1, -obj.raw_length(), obj) )
     magic.sort()
-    # Build a map of objects and their index in magic - so we can find preceeding objects
-    # to diff against
+    # Build a map of objects and their index in magic - so we can find
+    # preceeding objects to diff against
     offs = {}
     for i in range(len(magic)):
         offs[magic[i][4]] = i
     # Write the pack
     entries = []
     f = SHA1Writer(f)
-    f.write("PACK")               # Pack header
-    f.write(struct.pack(">L", 2)) # Pack version
-    f.write(struct.pack(">L", num_objects)) # Number of objects in pack
+    write_pack_header(f, num_objects)
     for o, path in recency:
         sha1 = o.sha().digest()
-        orig_t = o.type
+        orig_t = o.type_num
         raw = o.as_raw_string()
         winner = raw
         t = orig_t
         #for i in range(offs[o]-window, window):
         #    if i < 0 or i >= len(offs): continue
         #    b = magic[i][4]
-        #    if b.type != orig_t: continue
+        #    if b.type_num != orig_t: continue
         #    base = b.as_raw_string()
         #    delta = create_delta(base, raw)
         #    if len(delta) < len(winner):
@@ -865,15 +1193,15 @@
     return entries, f.write_sha()
 
 
-def write_pack_index_v1(filename, entries, pack_checksum):
+def write_pack_index_v1(f, entries, pack_checksum):
     """Write a new pack index file.
 
-    :param filename: The filename of the new pack index file.
-    :param entries: List of tuples with object name (sha), offset_in_pack,  and
-            crc32_checksum.
+    :param f: A file-like object to write to
+    :param entries: List of tuples with object name (sha), offset_in_pack,
+        and crc32_checksum.
     :param pack_checksum: Checksum of the pack file.
+    :return: The SHA of the written index file
     """
-    f = open(filename, 'wb')
     f = SHA1Writer(f)
     fan_out_table = defaultdict(lambda: 0)
     for (name, offset, entry_checksum) in entries:
@@ -886,7 +1214,7 @@
         f.write(struct.pack(">L20s", offset, name))
     assert len(pack_checksum) == 20
     f.write(pack_checksum)
-    f.close()
+    return f.write_sha()
 
 
 def create_delta(base_buf, target_buf):
@@ -951,12 +1279,14 @@
 
 def apply_delta(src_buf, delta):
     """Based on the similar function in git's patch-delta.c.
-    
+
     :param src_buf: Source buffer
     :param delta: Delta instructions
     """
-    assert isinstance(src_buf, str), "was %r" % (src_buf,)
-    assert isinstance(delta, str)
+    if type(src_buf) != str:
+        src_buf = "".join(src_buf)
+    if type(delta) != str:
+        delta = "".join(delta)
     out = []
     index = 0
     delta_length = len(delta)
@@ -980,17 +1310,17 @@
         if cmd & 0x80:
             cp_off = 0
             for i in range(4):
-                if cmd & (1 << i): 
+                if cmd & (1 << i):
                     x = ord(delta[index])
                     index += 1
                     cp_off |= x << (i * 8)
             cp_size = 0
             for i in range(3):
-                if cmd & (1 << (4+i)): 
+                if cmd & (1 << (4+i)):
                     x = ord(delta[index])
                     index += 1
                     cp_size |= x << (i * 8)
-            if cp_size == 0: 
+            if cp_size == 0:
                 cp_size = 0x10000
             if (cp_off + cp_size < cp_size or
                 cp_off + cp_size > src_size or
@@ -1002,26 +1332,25 @@
             index += cmd
         else:
             raise ApplyDeltaError("Invalid opcode 0")
-    
+
     if index != delta_length:
         raise ApplyDeltaError("delta not empty: %r" % delta[index:])
 
-    out = ''.join(out)
-    if dest_size != len(out):
+    if dest_size != chunks_length(out):
         raise ApplyDeltaError("dest size incorrect")
 
     return out
 
 
-def write_pack_index_v2(filename, entries, pack_checksum):
+def write_pack_index_v2(f, entries, pack_checksum):
     """Write a new pack index file.
 
-    :param filename: The filename of the new pack index file.
-    :param entries: List of tuples with object name (sha), offset_in_pack,  and
-            crc32_checksum.
+    :param f: File-like object to write to
+    :param entries: List of tuples with object name (sha), offset_in_pack, and
+        crc32_checksum.
     :param pack_checksum: Checksum of the pack file.
+    :return: The SHA of the index file written
     """
-    f = open(filename, 'wb')
     f = SHA1Writer(f)
     f.write('\377tOc') # Magic!
     f.write(struct.pack(">L", 2))
@@ -1042,7 +1371,7 @@
     # FIXME: handle table for pack files > 8 Gb
     assert len(pack_checksum) == 20
     f.write(pack_checksum)
-    f.close()
+    return f.write_sha()
 
 
 class Pack(object):
@@ -1050,17 +1379,28 @@
 
     def __init__(self, basename):
         self._basename = basename
-        self._data_path = self._basename + ".pack"
-        self._idx_path = self._basename + ".idx"
         self._data = None
         self._idx = None
+        self._idx_path = self._basename + ".idx"
+        self._data_path = self._basename + ".pack"
+        self._data_load = lambda: PackData(self._data_path)
+        self._idx_load = lambda: load_pack_index(self._idx_path)
+
+    @classmethod
+    def from_lazy_objects(self, data_fn, idx_fn):
+        """Create a new pack object from callables to load pack data and 
+        index objects."""
+        ret = Pack("")
+        ret._data_load = data_fn
+        ret._idx_load = idx_fn
+        return ret
 
     @classmethod
     def from_objects(self, data, idx):
         """Create a new pack object from pack data and index objects."""
         ret = Pack("")
-        ret._data = data
-        ret._idx = idx
+        ret._data_load = lambda: data
+        ret._idx_load = lambda: idx
         return ret
 
     def name(self):
@@ -1071,12 +1411,13 @@
     def data(self):
         """The pack data object being used."""
         if self._data is None:
-            self._data = PackData(self._data_path)
+            self._data = self._data_load()
+            self._data.pack = self
             assert len(self.index) == len(self._data)
             idx_stored_checksum = self.index.get_pack_checksum()
             data_stored_checksum = self._data.get_stored_checksum()
             if idx_stored_checksum != data_stored_checksum:
-                raise ChecksumMismatch(sha_to_hex(idx_stored_checksum), 
+                raise ChecksumMismatch(sha_to_hex(idx_stored_checksum),
                                        sha_to_hex(data_stored_checksum))
         return self._data
 
@@ -1087,7 +1428,7 @@
         :note: This may be an in-memory index
         """
         if self._idx is None:
-            self._idx = load_pack_index(self._idx_path)
+            self._idx = self._idx_load()
         return self._idx
 
     def close(self):
@@ -1110,12 +1451,15 @@
         return iter(self.index)
 
     def check(self):
-        """Check the integrity of this pack."""
-        if not self.index.check():
-            return False
-        if not self.data.check():
-            return False
-        return True
+        """Check the integrity of this pack.
+
+        :raise ChecksumMismatch: if a checksum for the index or data is wrong
+        """
+        self.index.check()
+        self.data.check()
+        for obj in self.iterobjects():
+            obj.check()
+        # TODO: object connectivity checks
 
     def get_stored_checksum(self):
         return self.data.get_stored_checksum()
@@ -1128,28 +1472,25 @@
         except KeyError:
             return False
 
-    def get_raw(self, sha1, resolve_ref=None):
+    def get_raw(self, sha1):
         offset = self.index.object_index(sha1)
         obj_type, obj = self.data.get_object_at(offset)
         if type(offset) is long:
           offset = int(offset)
-        if resolve_ref is None:
-            resolve_ref = self.get_raw
-        return self.data.resolve_object(offset, obj_type, obj, resolve_ref)
+        type_num, chunks = self.data.resolve_object(offset, obj_type, obj)
+        return type_num, "".join(chunks)
 
     def __getitem__(self, sha1):
         """Retrieve the specified SHA1."""
         type, uncomp = self.get_raw(sha1)
         return ShaFile.from_raw_string(type, uncomp)
 
-    def iterobjects(self, get_raw=None):
+    def iterobjects(self):
         """Iterate over the objects in this pack."""
-        if get_raw is None:
-            get_raw = self.get_raw
         for offset, type, obj, crc32 in self.data.iterobjects():
             assert isinstance(offset, int)
-            yield ShaFile.from_raw_string(
-                    *self.data.resolve_object(offset, type, obj, get_raw))
+            yield ShaFile.from_raw_chunks(
+              *self.data.resolve_object(offset, type, obj))
 
 
 try:

=== modified file 'dulwich/patch.py'
--- dulwich/patch.py	2009-10-10 10:33:32 +0000
+++ dulwich/patch.py	2010-11-21 13:59:50 +0000
@@ -1,16 +1,16 @@
-# patch.py -- For dealing wih packed-style patches.
-# Copryight (C) 2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+# patch.py -- For dealing with packed-style patches.
+# Copyright (C) 2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
+#
 # 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) a later version.
-# 
+#
 # 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,
@@ -18,14 +18,19 @@
 
 """Classes for dealing with git am-style patches.
 
-These patches are basically unified diffs with some extra metadata tacked 
+These patches are basically unified diffs with some extra metadata tacked
 on.
 """
 
-import difflib
+from difflib import SequenceMatcher
+import rfc822
 import subprocess
 import time
 
+from dulwich.objects import (
+    Blob,
+    Commit,
+    )
 
 def write_commit_patch(f, commit, contents, progress, version=None):
     """Write a individual file patch.
@@ -42,7 +47,7 @@
     f.write("\n")
     f.write("---\n")
     try:
-        p = subprocess.Popen(["diffstat"], stdout=subprocess.PIPE, 
+        p = subprocess.Popen(["diffstat"], stdout=subprocess.PIPE,
                              stdin=subprocess.PIPE)
     except OSError, e:
         pass # diffstat not available?
@@ -61,14 +66,44 @@
 
 def get_summary(commit):
     """Determine the summary line for use in a filename.
-    
+
     :param commit: Commit
     :return: Summary string
     """
     return commit.message.splitlines()[0].replace(" ", "-")
 
 
-def write_blob_diff(f, (old_path, old_mode, old_blob), 
+def unified_diff(a, b, fromfile='', tofile='', n=3):
+    """difflib.unified_diff that doesn't write any dates or trailing spaces.
+
+    Based on the same function in Python2.6.5-rc2's difflib.py
+    """
+    started = False
+    for group in SequenceMatcher(None, a, b).get_grouped_opcodes(n):
+        if not started:
+            yield '--- %s\n' % fromfile
+            yield '+++ %s\n' % tofile
+            started = True
+        i1, i2, j1, j2 = group[0][1], group[-1][2], group[0][3], group[-1][4]
+        yield "@@ -%d,%d +%d,%d @@\n" % (i1+1, i2-i1, j1+1, j2-j1)
+        for tag, i1, i2, j1, j2 in group:
+            if tag == 'equal':
+                for line in a[i1:i2]:
+                    yield ' ' + line
+                continue
+            if tag == 'replace' or tag == 'delete':
+                for line in a[i1:i2]:
+                    if not line[-1] == '\n':
+                        line += '\n\\ No newline at end of file\n'
+                    yield '-' + line
+            if tag == 'replace' or tag == 'insert':
+                for line in b[j1:j2]:
+                    if not line[-1] == '\n':
+                        line += '\n\\ No newline at end of file\n'
+                    yield '+' + line
+
+
+def write_blob_diff(f, (old_path, old_mode, old_blob),
                        (new_path, new_mode, new_blob)):
     """Write diff file header.
 
@@ -98,13 +133,78 @@
     if old_mode != new_mode:
         if new_mode is not None:
             if old_mode is not None:
-                f.write("old file mode %o\n" % old_mode)
-            f.write("new file mode %o\n" % new_mode) 
+                f.write("old mode %o\n" % old_mode)
+            f.write("new mode %o\n" % new_mode)
         else:
-            f.write("deleted file mode %o\n" % old_mode)
-    f.write("index %s..%s %o\n" % (
-        blob_id(old_blob), blob_id(new_blob), new_mode))
+            f.write("deleted mode %o\n" % old_mode)
+    f.write("index %s..%s" % (blob_id(old_blob), blob_id(new_blob)))
+    if new_mode is not None:
+        f.write(" %o" % new_mode)
+    f.write("\n")
     old_contents = lines(old_blob)
     new_contents = lines(new_blob)
-    f.writelines(difflib.unified_diff(old_contents, new_contents, 
+    f.writelines(unified_diff(old_contents, new_contents,
         old_path, new_path))
+
+
+def write_tree_diff(f, store, old_tree, new_tree):
+    """Write tree diff.
+
+    :param f: File-like object to write to.
+    :param old_tree: Old tree id
+    :param new_tree: New tree id
+    """
+    changes = store.tree_changes(old_tree, new_tree)
+    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
+        if oldsha is None:
+            old_blob = Blob.from_string("")
+        else:
+            old_blob = store[oldsha]
+        if newsha is None:
+            new_blob = Blob.from_string("")
+        else:
+            new_blob = store[newsha]
+        write_blob_diff(f, (oldpath, oldmode, old_blob),
+                           (newpath, newmode, new_blob))
+
+
+def git_am_patch_split(f):
+    """Parse a git-am-style patch and split it up into bits.
+
+    :param f: File-like object to parse
+    :return: Tuple with commit object, diff contents and git version
+    """
+    msg = rfc822.Message(f)
+    c = Commit()
+    c.author = msg["from"]
+    c.committer = msg["from"]
+    try:
+        patch_tag_start = msg["subject"].index("[PATCH")
+    except ValueError:
+        subject = msg["subject"]
+    else:
+        close = msg["subject"].index("] ", patch_tag_start)
+        subject = msg["subject"][close+2:]
+    c.message = subject.replace("\n", "") + "\n"
+    first = True
+    for l in f:
+        if l == "---\n":
+            break
+        if first:
+            if l.startswith("From: "):
+                c.author = l[len("From: "):].rstrip()
+            else:
+                c.message += "\n" + l
+            first = False
+        else:
+            c.message += l
+    diff = ""
+    for l in f:
+        if l == "-- \n":
+            break
+        diff += l
+    try:
+        version = f.next().rstrip("\n")
+    except StopIteration:
+        version = None
+    return c, diff, version

=== modified file 'dulwich/protocol.py'
--- dulwich/protocol.py	2009-05-05 03:10:43 +0000
+++ dulwich/protocol.py	2010-12-21 09:52:59 +0000
@@ -1,5 +1,5 @@
 # protocol.py -- Shared parts of the git protocols
-# Copryight (C) 2008 John Carr <john.carr@xxxxxxxxxxxxxx>
+# Copyright (C) 2008 John Carr <john.carr@xxxxxxxxxxxxxx>
 # Copyright (C) 2008 Jelmer Vernooij <jelmer@xxxxxxxxx>
 #
 # This program is free software; you can redistribute it and/or
@@ -19,20 +19,28 @@
 
 """Generic functions for talking the git smart server protocol."""
 
+from cStringIO import StringIO
 import socket
 
 from dulwich.errors import (
     HangupException,
     GitProtocolError,
     )
+from dulwich._compat import (
+    SEEK_END,
+    )
 
 TCP_GIT_PORT = 9418
 
+ZERO_SHA = "0" * 40
+
+SINGLE_ACK = 0
+MULTI_ACK = 1
+MULTI_ACK_DETAILED = 2
+
+
 class ProtocolFile(object):
-    """
-    Some network ops are like file ops. The file ops expect to operate on
-    file objects, so provide them with a dummy file.
-    """
+    """A dummy file for network ops that expect file-like objects."""
 
     def __init__(self, read, write):
         self.read = read
@@ -45,21 +53,52 @@
         pass
 
 
+def pkt_line(data):
+    """Wrap data in a pkt-line.
+
+    :param data: The data to wrap, as a str or None.
+    :return: The data prefixed with its length in pkt-line format; if data was
+        None, returns the flush-pkt ('0000').
+    """
+    if data is None:
+        return '0000'
+    return '%04x%s' % (len(data) + 4, data)
+
+
 class Protocol(object):
+    """Class for interacting with a remote git process over the wire.
+
+    Parts of the git wire protocol use 'pkt-lines' to communicate. A pkt-line
+    consists of the length of the line as a 4-byte hex string, followed by the
+    payload data. The length includes the 4-byte header. The special line '0000'
+    indicates the end of a section of input and is called a 'flush-pkt'.
+
+    For details on the pkt-line format, see the cgit distribution:
+        Documentation/technical/protocol-common.txt
+    """
 
     def __init__(self, read, write, report_activity=None):
         self.read = read
         self.write = write
         self.report_activity = report_activity
+        self._readahead = None
 
     def read_pkt_line(self):
-        """
-        Reads a 'pkt line' from the remote git process
-
-        :return: The next string from the stream
-        """
+        """Reads a pkt-line from the remote git process.
+
+        This method may read from the readahead buffer; see unread_pkt_line.
+
+        :return: The next string from the stream, without the length prefix, or
+            None for a flush-pkt ('0000').
+        """
+        if self._readahead is None:
+            read = self.read
+        else:
+            read = self._readahead.read
+            self._readahead = None
+
         try:
-            sizestr = self.read(4)
+            sizestr = read(4)
             if not sizestr:
                 raise HangupException()
             size = int(sizestr, 16)
@@ -69,35 +108,64 @@
                 return None
             if self.report_activity:
                 self.report_activity(size, 'read')
-            return self.read(size-4)
+            return read(size-4)
         except socket.error, e:
             raise GitProtocolError(e)
 
+    def eof(self):
+        """Test whether the protocol stream has reached EOF.
+
+        Note that this refers to the actual stream EOF and not just a flush-pkt.
+
+        :return: True if the stream is at EOF, False otherwise.
+        """
+        try:
+            next_line = self.read_pkt_line()
+        except HangupException:
+            return True
+        self.unread_pkt_line(next_line)
+        return False
+
+    def unread_pkt_line(self, data):
+        """Unread a single line of data into the readahead buffer.
+
+        This method can be used to unread a single pkt-line into a fixed
+        readahead buffer.
+
+        :param data: The data to unread, without the length prefix.
+        :raise ValueError: If more than one pkt-line is unread.
+        """
+        if self._readahead is not None:
+            raise ValueError('Attempted to unread multiple pkt-lines.')
+        self._readahead = StringIO(pkt_line(data))
+
     def read_pkt_seq(self):
+        """Read a sequence of pkt-lines from the remote git process.
+
+        :return: Yields each line of data up to but not including the next flush-pkt.
+        """
         pkt = self.read_pkt_line()
         while pkt:
             yield pkt
             pkt = self.read_pkt_line()
 
     def write_pkt_line(self, line):
-        """
-        Sends a 'pkt line' to the remote git process
+        """Sends a pkt-line to the remote git process.
 
-        :param line: A string containing the data to send
+        :param line: A string containing the data to send, without the length
+            prefix.
         """
         try:
-            if line is None:
-                self.write("0000")
-                if self.report_activity:
-                    self.report_activity(4, 'write')
-            else:
-                self.write("%04x%s" % (len(line)+4, line))
-                if self.report_activity:
-                    self.report_activity(4+len(line), 'write')
+            line = pkt_line(line)
+            self.write(line)
+            if self.report_activity:
+                self.report_activity(len(line), 'write')
         except socket.error, e:
             raise GitProtocolError(e)
 
     def write_file(self):
+        """Return a writable file-like object for this protocol."""
+
         class ProtocolFile(object):
 
             def __init__(self, proto):
@@ -117,11 +185,10 @@
         return ProtocolFile(self)
 
     def write_sideband(self, channel, blob):
-        """
-        Write data to the sideband (a git multiplexing method)
+        """Write multiplexed data to the sideband.
 
-        :param channel: int specifying which channel to write to
-        :param blob: a blob of data (as a string) to send on this channel
+        :param channel: An int specifying the channel to write to.
+        :param blob: A blob of data (as a string) to send on this channel.
         """
         # a pktline can be a max of 65520. a sideband line can therefore be
         # 65520-5 = 65515
@@ -131,23 +198,21 @@
             blob = blob[65515:]
 
     def send_cmd(self, cmd, *args):
-        """
-        Send a command and some arguments to a git server
-
-        Only used for git://
-
-        :param cmd: The remote service to access
-        :param args: List of arguments to send to remove service
+        """Send a command and some arguments to a git server.
+
+        Only used for the TCP git protocol (git://).
+
+        :param cmd: The remote service to access.
+        :param args: List of arguments to send to remove service.
         """
         self.write_pkt_line("%s %s" % (cmd, "".join(["%s\0" % a for a in args])))
 
     def read_cmd(self):
-        """
-        Read a command and some arguments from the git client
-
-        Only used for git://
-
-        :return: A tuple of (command, [list of arguments])
+        """Read a command and some arguments from the git client
+
+        Only used for the TCP git protocol (git://).
+
+        :return: A tuple of (command, [list of arguments]).
         """
         line = self.read_pkt_line()
         splice_at = line.find(" ")
@@ -156,15 +221,188 @@
         return cmd, args[:-1].split(chr(0))
 
 
+_RBUFSIZE = 8192  # Default read buffer size.
+
+
+class ReceivableProtocol(Protocol):
+    """Variant of Protocol that allows reading up to a size without blocking.
+
+    This class has a recv() method that behaves like socket.recv() in addition
+    to a read() method.
+
+    If you want to read n bytes from the wire and block until exactly n bytes
+    (or EOF) are read, use read(n). If you want to read at most n bytes from the
+    wire but don't care if you get less, use recv(n). Note that recv(n) will
+    still block until at least one byte is read.
+    """
+
+    def __init__(self, recv, write, report_activity=None, rbufsize=_RBUFSIZE):
+        super(ReceivableProtocol, self).__init__(self.read, write,
+                                                 report_activity)
+        self._recv = recv
+        self._rbuf = StringIO()
+        self._rbufsize = rbufsize
+
+    def read(self, size):
+        # From _fileobj.read in socket.py in the Python 2.6.5 standard library,
+        # with the following modifications:
+        #  - omit the size <= 0 branch
+        #  - seek back to start rather than 0 in case some buffer has been
+        #    consumed.
+        #  - use SEEK_END instead of the magic number.
+        # Copyright (c) 2001-2010 Python Software Foundation; All Rights Reserved
+        # Licensed under the Python Software Foundation License.
+        # TODO: see if buffer is more efficient than cStringIO.
+        assert size > 0
+
+        # Our use of StringIO rather than lists of string objects returned by
+        # recv() minimizes memory usage and fragmentation that occurs when
+        # rbufsize is large compared to the typical return value of recv().
+        buf = self._rbuf
+        start = buf.tell()
+        buf.seek(0, SEEK_END)
+        # buffer may have been partially consumed by recv()
+        buf_len = buf.tell() - start
+        if buf_len >= size:
+            # Already have size bytes in our buffer?  Extract and return.
+            buf.seek(start)
+            rv = buf.read(size)
+            self._rbuf = StringIO()
+            self._rbuf.write(buf.read())
+            self._rbuf.seek(0)
+            return rv
+
+        self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.
+        while True:
+            left = size - buf_len
+            # recv() will malloc the amount of memory given as its
+            # parameter even though it often returns much less data
+            # than that.  The returned data string is short lived
+            # as we copy it into a StringIO and free it.  This avoids
+            # fragmentation issues on many platforms.
+            data = self._recv(left)
+            if not data:
+                break
+            n = len(data)
+            if n == size and not buf_len:
+                # Shortcut.  Avoid buffer data copies when:
+                # - We have no data in our buffer.
+                # AND
+                # - Our call to recv returned exactly the
+                #   number of bytes we were asked to read.
+                return data
+            if n == left:
+                buf.write(data)
+                del data  # explicit free
+                break
+            assert n <= left, "_recv(%d) returned %d bytes" % (left, n)
+            buf.write(data)
+            buf_len += n
+            del data  # explicit free
+            #assert buf_len == buf.tell()
+        buf.seek(start)
+        return buf.read()
+
+    def recv(self, size):
+        assert size > 0
+
+        buf = self._rbuf
+        start = buf.tell()
+        buf.seek(0, SEEK_END)
+        buf_len = buf.tell()
+        buf.seek(start)
+
+        left = buf_len - start
+        if not left:
+            # only read from the wire if our read buffer is exhausted
+            data = self._recv(self._rbufsize)
+            if len(data) == size:
+                # shortcut: skip the buffer if we read exactly size bytes
+                return data
+            buf = StringIO()
+            buf.write(data)
+            buf.seek(0)
+            del data  # explicit free
+            self._rbuf = buf
+        return buf.read(size)
+
+
 def extract_capabilities(text):
     """Extract a capabilities list from a string, if present.
 
     :param text: String to extract from
-    :return: Tuple with text with capabilities removed and list of 
-        capabilities or None (if no capabilities were present.
+    :return: Tuple with text with capabilities removed and list of capabilities
     """
     if not "\0" in text:
-        return text, None
-    capabilities = text.split("\0")
-    return (capabilities[0], capabilities[1:])
-
+        return text, []
+    text, capabilities = text.rstrip().split("\0")
+    return (text, capabilities.strip().split(" "))
+
+
+def extract_want_line_capabilities(text):
+    """Extract a capabilities list from a want line, if present.
+
+    Note that want lines have capabilities separated from the rest of the line
+    by a space instead of a null byte. Thus want lines have the form:
+
+        want obj-id cap1 cap2 ...
+
+    :param text: Want line to extract from
+    :return: Tuple with text with capabilities removed and list of capabilities
+    """
+    split_text = text.rstrip().split(" ")
+    if len(split_text) < 3:
+        return text, []
+    return (" ".join(split_text[:2]), split_text[2:])
+
+
+def ack_type(capabilities):
+    """Extract the ack type from a capabilities list."""
+    if 'multi_ack_detailed' in capabilities:
+        return MULTI_ACK_DETAILED
+    elif 'multi_ack' in capabilities:
+        return MULTI_ACK
+    return SINGLE_ACK
+
+
+class BufferedPktLineWriter(object):
+    """Writer that wraps its data in pkt-lines and has an independent buffer.
+
+    Consecutive calls to write() wrap the data in a pkt-line and then buffers it
+    until enough lines have been written such that their total length (including
+    length prefix) reach the buffer size.
+    """
+
+    def __init__(self, write, bufsize=65515):
+        """Initialize the BufferedPktLineWriter.
+
+        :param write: A write callback for the underlying writer.
+        :param bufsize: The internal buffer size, including length prefixes.
+        """
+        self._write = write
+        self._bufsize = bufsize
+        self._wbuf = StringIO()
+        self._buflen = 0
+
+    def write(self, data):
+        """Write data, wrapping it in a pkt-line."""
+        line = pkt_line(data)
+        line_len = len(line)
+        over = self._buflen + line_len - self._bufsize
+        if over >= 0:
+            start = line_len - over
+            self._wbuf.write(line[:start])
+            self.flush()
+        else:
+            start = 0
+        saved = line[start:]
+        self._wbuf.write(saved)
+        self._buflen += len(saved)
+
+    def flush(self):
+        """Flush all data from the buffer."""
+        data = self._wbuf.getvalue()
+        if data:
+            self._write(data)
+        self._len = 0
+        self._wbuf = StringIO()

=== modified file 'dulwich/repo.py'
--- dulwich/repo.py	2009-10-18 17:24:17 +0000
+++ dulwich/repo.py	2011-01-17 06:00:40 +0000
@@ -1,18 +1,18 @@
-# repo.py -- For dealing wih git repositories.
+# repo.py -- For dealing with git repositories.
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
 # Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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 
+# 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,
@@ -21,19 +21,29 @@
 
 """Repository access."""
 
-
+from cStringIO import StringIO
+import errno
 import os
-import stat
 
 from dulwich.errors import (
-    MissingCommitError, 
-    NotBlobError, 
-    NotCommitError, 
+    MissingCommitError,
+    NoIndexPresent,
+    NotBlobError,
+    NotCommitError,
     NotGitRepository,
-    NotTreeError, 
+    NotTreeError,
+    NotTagError,
+    PackedRefsException,
+    CommitError,
+    RefFormatError,
+    )
+from dulwich.file import (
+    ensure_dir_exists,
+    GitFile,
     )
 from dulwich.object_store import (
     DiskObjectStore,
+    MemoryObjectStore,
     )
 from dulwich.objects import (
     Blob,
@@ -41,7 +51,10 @@
     ShaFile,
     Tag,
     Tree,
+    hex_to_sha,
     )
+import warnings
+
 
 OBJECTDIR = 'objects'
 SYMREF = 'ref: '
@@ -50,104 +63,372 @@
 REFSDIR_HEADS = 'heads'
 INDEX_FILENAME = "index"
 
-
-def follow_ref(container, name):
-    """Follow a ref back to a SHA1.
-    
-    :param container: Ref container to use for looking up refs.
-    :param name: Name of the original ref.
+BASE_DIRECTORIES = [
+    ["branches"],
+    [REFSDIR],
+    [REFSDIR, REFSDIR_TAGS],
+    [REFSDIR, REFSDIR_HEADS],
+    ["hooks"],
+    ["info"]
+    ]
+
+
+def read_info_refs(f):
+    ret = {}
+    for l in f.readlines():
+        (sha, name) = l.rstrip("\r\n").split("\t", 1)
+        ret[name] = sha
+    return ret
+
+
+def check_ref_format(refname):
+    """Check if a refname is correctly formatted.
+
+    Implements all the same rules as git-check-ref-format[1].
+
+    [1] http://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
+
+    :param refname: The refname to check
+    :return: True if refname is valid, False otherwise
     """
-    contents = container[name]
-    if contents.startswith(SYMREF):
-        ref = contents[len(SYMREF):]
-        if ref[-1] == '\n':
-            ref = ref[:-1]
-        return follow_ref(container, ref)
-    assert len(contents) == 40, 'Invalid ref in %s' % name
-    return contents
+    # These could be combined into one big expression, but are listed separately
+    # to parallel [1].
+    if '/.' in refname or refname.startswith('.'):
+        return False
+    if '/' not in refname:
+        return False
+    if '..' in refname:
+        return False
+    for c in refname:
+        if ord(c) < 040 or c in '\177 ~^:?*[':
+            return False
+    if refname[-1] in '/.':
+        return False
+    if refname.endswith('.lock'):
+        return False
+    if '@{' in refname:
+        return False
+    if '\\' in refname:
+        return False
+    return True
 
 
 class RefsContainer(object):
     """A container for refs."""
 
-    def as_dict(self, base):
-        """Return the contents of this ref container under base as a dict."""
-        raise NotImplementedError(self.as_dict)
-
-    def follow(self, name):
-        """Follow a ref name back to a SHA1.
-        
-        :param name: Name of the ref
-        """
-        return follow_ref(self, name)
-
     def set_ref(self, name, other):
+        warnings.warn("RefsContainer.set_ref() is deprecated."
+            "Use set_symblic_ref instead.",
+            category=DeprecationWarning, stacklevel=2)
+        return self.set_symbolic_ref(name, other)
+
+    def set_symbolic_ref(self, name, other):
         """Make a ref point at another ref.
 
         :param name: Name of the ref to set
         :param other: Name of the ref to point at
         """
-        self[name] = "ref: %s\n" % other
+        raise NotImplementedError(self.set_symbolic_ref)
+
+    def get_packed_refs(self):
+        """Get contents of the packed-refs file.
+
+        :return: Dictionary mapping ref names to SHA1s
+
+        :note: Will return an empty dictionary when no packed-refs file is
+            present.
+        """
+        raise NotImplementedError(self.get_packed_refs)
+
+    def get_peeled(self, name):
+        """Return the cached peeled value of a ref, if available.
+
+        :param name: Name of the ref to peel
+        :return: The peeled value of the ref. If the ref is known not point to a
+            tag, this will be the SHA the ref refers to. If the ref may point to
+            a tag, but no cached information is available, None is returned.
+        """
+        return None
 
     def import_refs(self, base, other):
         for name, value in other.iteritems():
             self["%s/%s" % (base, name)] = value
 
+    def allkeys(self):
+        """All refs present in this container."""
+        raise NotImplementedError(self.allkeys)
+
+    def keys(self, base=None):
+        """Refs present in this container.
+
+        :param base: An optional base to return refs under.
+        :return: An unsorted set of valid refs in this container, including
+            packed refs.
+        """
+        if base is not None:
+            return self.subkeys(base)
+        else:
+            return self.allkeys()
+
+    def subkeys(self, base):
+        """Refs present in this container under a base.
+
+        :param base: The base to return refs under.
+        :return: A set of valid refs in this container under the base; the base
+            prefix is stripped from the ref names returned.
+        """
+        keys = set()
+        base_len = len(base) + 1
+        for refname in self.allkeys():
+            if refname.startswith(base):
+                keys.add(refname[base_len:])
+        return keys
+
+    def as_dict(self, base=None):
+        """Return the contents of this container as a dictionary.
+
+        """
+        ret = {}
+        keys = self.keys(base)
+        if base is None:
+            base = ""
+        for key in keys:
+            try:
+                ret[key] = self[("%s/%s" % (base, key)).strip("/")]
+            except KeyError:
+                continue # Unable to resolve
+
+        return ret
+
+    def _check_refname(self, name):
+        """Ensure a refname is valid and lives in refs or is HEAD.
+
+        HEAD is not a valid refname according to git-check-ref-format, but this
+        class needs to be able to touch HEAD. Also, check_ref_format expects
+        refnames without the leading 'refs/', but this class requires that
+        so it cannot touch anything outside the refs dir (or HEAD).
+
+        :param name: The name of the reference.
+        :raises KeyError: if a refname is not HEAD or is otherwise not valid.
+        """
+        if name == 'HEAD':
+            return
+        if not name.startswith('refs/') or not check_ref_format(name[5:]):
+            raise RefFormatError(name)
+
+    def read_ref(self, refname):
+        """Read a reference without following any references.
+
+        :param refname: The name of the reference
+        :return: The contents of the ref file, or None if it does
+            not exist.
+        """
+        contents = self.read_loose_ref(refname)
+        if not contents:
+            contents = self.get_packed_refs().get(refname, None)
+        return contents
+
+    def read_loose_ref(self, name):
+        """Read a loose reference and return its contents.
+
+        :param name: the refname to read
+        :return: The contents of the ref file, or None if it does
+            not exist.
+        """
+        raise NotImplementedError(self.read_loose_ref)
+
+    def _follow(self, name):
+        """Follow a reference name.
+
+        :return: a tuple of (refname, sha), where refname is the name of the
+            last reference in the symbolic reference chain
+        """
+        contents = SYMREF + name
+        depth = 0
+        while contents.startswith(SYMREF):
+            refname = contents[len(SYMREF):]
+            contents = self.read_ref(refname)
+            if not contents:
+                break
+            depth += 1
+            if depth > 5:
+                raise KeyError(name)
+        return refname, contents
+
+    def __contains__(self, refname):
+        if self.read_ref(refname):
+            return True
+        return False
+
+    def __getitem__(self, name):
+        """Get the SHA1 for a reference name.
+
+        This method follows all symbolic references.
+        """
+        _, sha = self._follow(name)
+        if sha is None:
+            raise KeyError(name)
+        return sha
+
+    def set_if_equals(self, name, old_ref, new_ref):
+        """Set a refname to new_ref only if it currently equals old_ref.
+
+        This method follows all symbolic references if applicable for the
+        subclass, and can be used to perform an atomic compare-and-swap
+        operation.
+
+        :param name: The refname to set.
+        :param old_ref: The old sha the refname must refer to, or None to set
+            unconditionally.
+        :param new_ref: The new sha the refname will refer to.
+        :return: True if the set was successful, False otherwise.
+        """
+        raise NotImplementedError(self.set_if_equals)
+
+    def add_if_new(self, name, ref):
+        """Add a new reference only if it does not already exist."""
+        raise NotImplementedError(self.add_if_new)
+
+    def __setitem__(self, name, ref):
+        """Set a reference name to point to the given SHA1.
+
+        This method follows all symbolic references if applicable for the
+        subclass.
+
+        :note: This method unconditionally overwrites the contents of a
+            reference. To update atomically only if the reference has not
+            changed, use set_if_equals().
+        :param name: The refname to set.
+        :param ref: The new sha the refname will refer to.
+        """
+        self.set_if_equals(name, None, ref)
+
+    def remove_if_equals(self, name, old_ref):
+        """Remove a refname only if it currently equals old_ref.
+
+        This method does not follow symbolic references, even if applicable for
+        the subclass. It can be used to perform an atomic compare-and-delete
+        operation.
+
+        :param name: The refname to delete.
+        :param old_ref: The old sha the refname must refer to, or None to delete
+            unconditionally.
+        :return: True if the delete was successful, False otherwise.
+        """
+        raise NotImplementedError(self.remove_if_equals)
+
+    def __delitem__(self, name):
+        """Remove a refname.
+
+        This method does not follow symbolic references, even if applicable for
+        the subclass.
+
+        :note: This method unconditionally deletes the contents of a reference.
+            To delete atomically only if the reference has not changed, use
+            remove_if_equals().
+
+        :param name: The refname to delete.
+        """
+        self.remove_if_equals(name, None)
+
+
+class DictRefsContainer(RefsContainer):
+    """RefsContainer backed by a simple dict.
+
+    This container does not support symbolic or packed references and is not
+    threadsafe.
+    """
+
+    def __init__(self, refs):
+        self._refs = refs
+        self._peeled = {}
+
+    def allkeys(self):
+        return self._refs.keys()
+
+    def read_loose_ref(self, name):
+        return self._refs.get(name, None)
+
+    def get_packed_refs(self):
+        return {}
+
+    def set_symbolic_ref(self, name, other):
+        self._refs[name] = SYMREF + other
+
+    def set_if_equals(self, name, old_ref, new_ref):
+        if old_ref is not None and self._refs.get(name, None) != old_ref:
+            return False
+        realname, _ = self._follow(name)
+        self._check_refname(realname)
+        self._refs[realname] = new_ref
+        return True
+
+    def add_if_new(self, name, ref):
+        if name in self._refs:
+            return False
+        self._refs[name] = ref
+        return True
+
+    def remove_if_equals(self, name, old_ref):
+        if old_ref is not None and self._refs.get(name, None) != old_ref:
+            return False
+        del self._refs[name]
+        return True
+
+    def get_peeled(self, name):
+        return self._peeled.get(name)
+
+    def _update(self, refs):
+        """Update multiple refs; intended only for testing."""
+        # TODO(dborowitz): replace this with a public function that uses
+        # set_if_equal.
+        self._refs.update(refs)
+
+    def _update_peeled(self, peeled):
+        """Update cached peeled refs; intended only for testing."""
+        self._peeled.update(peeled)
+
 
 class DiskRefsContainer(RefsContainer):
     """Refs container that reads refs from disk."""
 
     def __init__(self, path):
         self.path = path
+        self._packed_refs = None
+        self._peeled_refs = None
 
     def __repr__(self):
         return "%s(%r)" % (self.__class__.__name__, self.path)
 
-    def keys(self, base=None):
-        """Refs present in this container."""
-        return list(self.iterkeys(base))
-
-    def iterkeys(self, base=None):
-        if base is not None:
-            return self.itersubkeys(base)
-        else:
-            return self.iterallkeys()
-
-    def itersubkeys(self, base):
+    def subkeys(self, base):
+        keys = set()
         path = self.refpath(base)
         for root, dirs, files in os.walk(path):
-            dir = root[len(path):].strip("/").replace(os.path.sep, "/")
+            dir = root[len(path):].strip(os.path.sep).replace(os.path.sep, "/")
             for filename in files:
-                yield ("%s/%s" % (dir, filename)).strip("/")
+                refname = ("%s/%s" % (dir, filename)).strip("/")
+                # check_ref_format requires at least one /, so we prepend the
+                # base before calling it.
+                if check_ref_format("%s/%s" % (base, refname)):
+                    keys.add(refname)
+        for key in self.get_packed_refs():
+            if key.startswith(base):
+                keys.add(key[len(base):].strip("/"))
+        return keys
 
-    def iterallkeys(self):
+    def allkeys(self):
+        keys = set()
         if os.path.exists(self.refpath("HEAD")):
-            yield "HEAD"
+            keys.add("HEAD")
         path = self.refpath("")
         for root, dirs, files in os.walk(self.refpath("refs")):
-            dir = root[len(path):].strip("/").replace(os.path.sep, "/")
+            dir = root[len(path):].strip(os.path.sep).replace(os.path.sep, "/")
             for filename in files:
-                yield ("%s/%s" % (dir, filename)).strip("/")
-
-    def as_dict(self, base=None, follow=True):
-        """Return the contents of this container as a dictionary.
-
-        """
-        ret = {}
-        if base is None:
-            keys = self.iterkeys()
-            base = ""
-        else:
-            keys = self.itersubkeys(base)
-        for key in keys:
-                if follow:
-                    try:
-                        ret[key] = self.follow(("%s/%s" % (base, key)).strip("/"))
-                    except KeyError:
-                        continue # Unable to resolve
-                else:
-                    ret[key] = self[("%s/%s" % (base, key)).strip("/")]
-        return ret
+                refname = ("%s/%s" % (dir, filename)).strip("/")
+                if check_ref_format(refname):
+                    keys.add(refname)
+        keys.update(self.get_packed_refs())
+        return keys
 
     def refpath(self, name):
         """Return the disk path of a ref.
@@ -157,120 +438,410 @@
             name = name.replace("/", os.path.sep)
         return os.path.join(self.path, name)
 
-    def __getitem__(self, name):
-        file = self.refpath(name)
-        if not os.path.exists(file):
-            raise KeyError(name)
-        f = open(file, 'rb')
-        try:
-            return f.read().strip("\n")
-        finally:
-            f.close()
-
-    def __setitem__(self, name, ref):
-        file = self.refpath(name)
-        dirpath = os.path.dirname(file)
-        if not os.path.exists(dirpath):
-            os.makedirs(dirpath)
-        f = open(file, 'wb')
-        try:
-            f.write(ref+"\n")
-        finally:
-            f.close()
-
-    def __delitem__(self, name):
-        file = self.refpath(name)
-        if os.path.exists(file):
-            os.remove(file)
+    def get_packed_refs(self):
+        """Get contents of the packed-refs file.
+
+        :return: Dictionary mapping ref names to SHA1s
+
+        :note: Will return an empty dictionary when no packed-refs file is
+            present.
+        """
+        # TODO: invalidate the cache on repacking
+        if self._packed_refs is None:
+            # set both to empty because we want _peeled_refs to be
+            # None if and only if _packed_refs is also None.
+            self._packed_refs = {}
+            self._peeled_refs = {}
+            path = os.path.join(self.path, 'packed-refs')
+            try:
+                f = GitFile(path, 'rb')
+            except IOError, e:
+                if e.errno == errno.ENOENT:
+                    return {}
+                raise
+            try:
+                first_line = iter(f).next().rstrip()
+                if (first_line.startswith("# pack-refs") and " peeled" in
+                        first_line):
+                    for sha, name, peeled in read_packed_refs_with_peeled(f):
+                        self._packed_refs[name] = sha
+                        if peeled:
+                            self._peeled_refs[name] = peeled
+                else:
+                    f.seek(0)
+                    for sha, name in read_packed_refs(f):
+                        self._packed_refs[name] = sha
+            finally:
+                f.close()
+        return self._packed_refs
+
+    def get_peeled(self, name):
+        """Return the cached peeled value of a ref, if available.
+
+        :param name: Name of the ref to peel
+        :return: The peeled value of the ref. If the ref is known not point to a
+            tag, this will be the SHA the ref refers to. If the ref may point to
+            a tag, but no cached information is available, None is returned.
+        """
+        self.get_packed_refs()
+        if self._peeled_refs is None or name not in self._packed_refs:
+            # No cache: no peeled refs were read, or this ref is loose
+            return None
+        if name in self._peeled_refs:
+            return self._peeled_refs[name]
+        else:
+            # Known not peelable
+            return self[name]
+
+    def read_loose_ref(self, name):
+        """Read a reference file and return its contents.
+
+        If the reference file a symbolic reference, only read the first line of
+        the file. Otherwise, only read the first 40 bytes.
+
+        :param name: the refname to read, relative to refpath
+        :return: The contents of the ref file, or None if the file does not
+            exist.
+        :raises IOError: if any other error occurs
+        """
+        filename = self.refpath(name)
+        try:
+            f = GitFile(filename, 'rb')
+            try:
+                header = f.read(len(SYMREF))
+                if header == SYMREF:
+                    # Read only the first line
+                    return header + iter(f).next().rstrip("\r\n")
+                else:
+                    # Read only the first 40 bytes
+                    return header + f.read(40-len(SYMREF))
+            finally:
+                f.close()
+        except IOError, e:
+            if e.errno == errno.ENOENT:
+                return None
+            raise
+
+    def _remove_packed_ref(self, name):
+        if self._packed_refs is None:
+            return
+        filename = os.path.join(self.path, 'packed-refs')
+        # reread cached refs from disk, while holding the lock
+        f = GitFile(filename, 'wb')
+        try:
+            self._packed_refs = None
+            self.get_packed_refs()
+
+            if name not in self._packed_refs:
+                return
+
+            del self._packed_refs[name]
+            if name in self._peeled_refs:
+                del self._peeled_refs[name]
+            write_packed_refs(f, self._packed_refs, self._peeled_refs)
+            f.close()
+        finally:
+            f.abort()
+
+    def set_symbolic_ref(self, name, other):
+        """Make a ref point at another ref.
+
+        :param name: Name of the ref to set
+        :param other: Name of the ref to point at
+        """
+        self._check_refname(name)
+        self._check_refname(other)
+        filename = self.refpath(name)
+        try:
+            f = GitFile(filename, 'wb')
+            try:
+                f.write(SYMREF + other + '\n')
+            except (IOError, OSError):
+                f.abort()
+                raise
+        finally:
+            f.close()
+
+    def set_if_equals(self, name, old_ref, new_ref):
+        """Set a refname to new_ref only if it currently equals old_ref.
+
+        This method follows all symbolic references, and can be used to perform
+        an atomic compare-and-swap operation.
+
+        :param name: The refname to set.
+        :param old_ref: The old sha the refname must refer to, or None to set
+            unconditionally.
+        :param new_ref: The new sha the refname will refer to.
+        :return: True if the set was successful, False otherwise.
+        """
+        self._check_refname(name)
+        try:
+            realname, _ = self._follow(name)
+        except KeyError:
+            realname = name
+        filename = self.refpath(realname)
+        ensure_dir_exists(os.path.dirname(filename))
+        f = GitFile(filename, 'wb')
+        try:
+            if old_ref is not None:
+                try:
+                    # read again while holding the lock
+                    orig_ref = self.read_loose_ref(realname)
+                    if orig_ref is None:
+                        orig_ref = self.get_packed_refs().get(realname, None)
+                    if orig_ref != old_ref:
+                        f.abort()
+                        return False
+                except (OSError, IOError):
+                    f.abort()
+                    raise
+            try:
+                f.write(new_ref+"\n")
+            except (OSError, IOError):
+                f.abort()
+                raise
+        finally:
+            f.close()
+        return True
+
+    def add_if_new(self, name, ref):
+        """Add a new reference only if it does not already exist.
+
+        This method follows symrefs, and only ensures that the last ref in the
+        chain does not exist.
+
+        :param name: The refname to set.
+        :param ref: The new sha the refname will refer to.
+        :return: True if the add was successful, False otherwise.
+        """
+        try:
+            realname, contents = self._follow(name)
+            if contents is not None:
+                return False
+        except KeyError:
+            realname = name
+        self._check_refname(realname)
+        filename = self.refpath(realname)
+        ensure_dir_exists(os.path.dirname(filename))
+        f = GitFile(filename, 'wb')
+        try:
+            if os.path.exists(filename) or name in self.get_packed_refs():
+                f.abort()
+                return False
+            try:
+                f.write(ref+"\n")
+            except (OSError, IOError):
+                f.abort()
+                raise
+        finally:
+            f.close()
+        return True
+
+    def remove_if_equals(self, name, old_ref):
+        """Remove a refname only if it currently equals old_ref.
+
+        This method does not follow symbolic references. It can be used to
+        perform an atomic compare-and-delete operation.
+
+        :param name: The refname to delete.
+        :param old_ref: The old sha the refname must refer to, or None to delete
+            unconditionally.
+        :return: True if the delete was successful, False otherwise.
+        """
+        self._check_refname(name)
+        filename = self.refpath(name)
+        ensure_dir_exists(os.path.dirname(filename))
+        f = GitFile(filename, 'wb')
+        try:
+            if old_ref is not None:
+                orig_ref = self.read_loose_ref(name)
+                if orig_ref is None:
+                    orig_ref = self.get_packed_refs().get(name, None)
+                if orig_ref != old_ref:
+                    return False
+            # may only be packed
+            try:
+                os.remove(filename)
+            except OSError, e:
+                if e.errno != errno.ENOENT:
+                    raise
+            self._remove_packed_ref(name)
+        finally:
+            # never write, we just wanted the lock
+            f.abort()
+        return True
+
+
+def _split_ref_line(line):
+    """Split a single ref line into a tuple of SHA1 and name."""
+    fields = line.rstrip("\n").split(" ")
+    if len(fields) != 2:
+        raise PackedRefsException("invalid ref line '%s'" % line)
+    sha, name = fields
+    try:
+        hex_to_sha(sha)
+    except (AssertionError, TypeError), e:
+        raise PackedRefsException(e)
+    if not check_ref_format(name):
+        raise PackedRefsException("invalid ref name '%s'" % name)
+    return (sha, name)
 
 
 def read_packed_refs(f):
     """Read a packed refs file.
 
-    Yields tuples with ref names and SHA1s.
-
     :param f: file-like object to read from
+    :return: Iterator over tuples with SHA1s and ref names.
     """
-    l = f.readline()
-    for l in f.readlines():
+    for l in f:
         if l[0] == "#":
             # Comment
             continue
         if l[0] == "^":
-            # FIXME: Return somehow
+            raise PackedRefsException(
+              "found peeled ref in packed-refs without peeled")
+        yield _split_ref_line(l)
+
+
+def read_packed_refs_with_peeled(f):
+    """Read a packed refs file including peeled refs.
+
+    Assumes the "# pack-refs with: peeled" line was already read. Yields tuples
+    with ref names, SHA1s, and peeled SHA1s (or None).
+
+    :param f: file-like object to read from, seek'ed to the second line
+    """
+    last = None
+    for l in f:
+        if l[0] == "#":
             continue
-        yield tuple(l.rstrip("\n").split(" ", 2))
-
-
-class Repo(object):
-    """A local git repository.
-    
-    :ivar refs: Dictionary with the refs in this repository
+        l = l.rstrip("\r\n")
+        if l[0] == "^":
+            if not last:
+                raise PackedRefsException("unexpected peeled ref line")
+            try:
+                hex_to_sha(l[1:])
+            except (AssertionError, TypeError), e:
+                raise PackedRefsException(e)
+            sha, name = _split_ref_line(last)
+            last = None
+            yield (sha, name, l[1:])
+        else:
+            if last:
+                sha, name = _split_ref_line(last)
+                yield (sha, name, None)
+            last = l
+    if last:
+        sha, name = _split_ref_line(last)
+        yield (sha, name, None)
+
+
+def write_packed_refs(f, packed_refs, peeled_refs=None):
+    """Write a packed refs file.
+
+    :param f: empty file-like object to write to
+    :param packed_refs: dict of refname to sha of packed refs to write
+    :param peeled_refs: dict of refname to peeled value of sha
+    """
+    if peeled_refs is None:
+        peeled_refs = {}
+    else:
+        f.write('# pack-refs with: peeled\n')
+    for refname in sorted(packed_refs.iterkeys()):
+        f.write('%s %s\n' % (packed_refs[refname], refname))
+        if refname in peeled_refs:
+            f.write('^%s\n' % peeled_refs[refname])
+
+
+class BaseRepo(object):
+    """Base class for a git repository.
+
     :ivar object_store: Dictionary-like object for accessing
         the objects
+    :ivar refs: Dictionary-like object with the refs in this repository
     """
 
-    def __init__(self, root):
-        if os.path.isdir(os.path.join(root, ".git", OBJECTDIR)):
-            self.bare = False
-            self._controldir = os.path.join(root, ".git")
-        elif (os.path.isdir(os.path.join(root, OBJECTDIR)) and
-              os.path.isdir(os.path.join(root, REFSDIR))):
-            self.bare = True
-            self._controldir = root
-        else:
-            raise NotGitRepository(root)
-        self.path = root
-        self.refs = DiskRefsContainer(self.controldir())
-        self.object_store = DiskObjectStore(
-            os.path.join(self.controldir(), OBJECTDIR))
-
-    def controldir(self):
-        """Return the path of the control directory."""
-        return self._controldir
-
-    def index_path(self):
-        """Return path to the index file."""
-        return os.path.join(self.controldir(), INDEX_FILENAME)
+    def __init__(self, object_store, refs):
+        self.object_store = object_store
+        self.refs = refs
+
+    def _init_files(self, bare):
+        """Initialize a default set of named files."""
+        self._put_named_file('description', "Unnamed repository")
+        self._put_named_file('config', ('[core]\n'
+                                        'repositoryformatversion = 0\n'
+                                        'filemode = true\n'
+                                        'bare = ' + str(bare).lower() + '\n'
+                                        'logallrefupdates = true\n'))
+        self._put_named_file(os.path.join('info', 'exclude'), '')
+
+    def get_named_file(self, path):
+        """Get a file from the control dir with a specific name.
+
+        Although the filename should be interpreted as a filename relative to
+        the control dir in a disk-based Repo, the object returned need not be
+        pointing to a file in that location.
+
+        :param path: The path to the file, relative to the control dir.
+        :return: An open file object, or None if the file does not exist.
+        """
+        raise NotImplementedError(self.get_named_file)
+
+    def _put_named_file(self, path, contents):
+        """Write a file to the control dir with the given name and contents.
+
+        :param path: The path to the file, relative to the control dir.
+        :param contents: A string to write to the file.
+        """
+        raise NotImplementedError(self._put_named_file)
 
     def open_index(self):
-        """Open the index for this repository."""
-        from dulwich.index import Index
-        return Index(self.index_path())
+        """Open the index for this repository.
 
-    def has_index(self):
-        """Check if an index is present."""
-        return os.path.exists(self.index_path())
+        :raises NoIndexPresent: If no index is present
+        :return: Index instance
+        """
+        raise NotImplementedError(self.open_index)
 
     def fetch(self, target, determine_wants=None, progress=None):
         """Fetch objects into another repository.
 
         :param target: The target repository
-        :param determine_wants: Optional function to determine what refs to 
+        :param determine_wants: Optional function to determine what refs to
             fetch.
         :param progress: Optional progress function
         """
+        if determine_wants is None:
+            determine_wants = lambda heads: heads.values()
         target.object_store.add_objects(
-            self.fetch_objects(determine_wants, target.get_graph_walker(),
-                progress))
+          self.fetch_objects(determine_wants, target.get_graph_walker(),
+                             progress))
         return self.get_refs()
 
-    def fetch_objects(self, determine_wants, graph_walker, progress):
+    def fetch_objects(self, determine_wants, graph_walker, progress,
+                      get_tagged=None):
         """Fetch the missing objects required for a set of revisions.
 
-        :param determine_wants: Function that takes a dictionary with heads 
+        :param determine_wants: Function that takes a dictionary with heads
             and returns the list of heads to fetch.
-        :param graph_walker: Object that can iterate over the list of revisions 
-            to fetch and has an "ack" method that will be called to acknowledge 
+        :param graph_walker: Object that can iterate over the list of revisions
+            to fetch and has an "ack" method that will be called to acknowledge
             that a revision is present.
-        :param progress: Simple progress function that will be called with 
+        :param progress: Simple progress function that will be called with
             updated progress strings.
+        :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+            sha for including tags.
         :return: iterator over objects, with __len__ implemented
         """
         wants = determine_wants(self.get_refs())
+        if wants is None:
+            # TODO(dborowitz): find a way to short-circuit that doesn't change
+            # this interface.
+            return None
         haves = self.object_store.find_common_revisions(graph_walker)
         return self.object_store.iter_shas(
-            self.object_store.find_missing_objects(haves, wants, progress))
+          self.object_store.find_missing_objects(haves, wants, progress,
+                                                 get_tagged))
 
     def get_graph_walker(self, heads=None):
         if heads is None:
@@ -279,59 +850,31 @@
 
     def ref(self, name):
         """Return the SHA1 a ref is pointing to."""
-        try:
-            return self.refs.follow(name)
-        except KeyError:
-            return self.get_packed_refs()[name]
+        return self.refs[name]
 
     def get_refs(self):
         """Get dictionary with all refs."""
-        ret = {}
-        try:
-            if self.head():
-                ret['HEAD'] = self.head()
-        except KeyError:
-            pass
-        ret.update(self.refs.as_dict())
-        ret.update(self.get_packed_refs())
-        return ret
-
-    def get_packed_refs(self):
-        """Get contents of the packed-refs file.
-
-        :return: Dictionary mapping ref names to SHA1s
-
-        :note: Will return an empty dictionary when no packed-refs file is 
-            present.
-        """
-        path = os.path.join(self.controldir(), 'packed-refs')
-        if not os.path.exists(path):
-            return {}
-        ret = {}
-        f = open(path, 'rb')
-        try:
-            for entry in read_packed_refs(f):
-                ret[entry[1]] = entry[0]
-            return ret
-        finally:
-            f.close()
+        return self.refs.as_dict()
 
     def head(self):
         """Return the SHA1 pointed at by HEAD."""
-        return self.refs.follow('HEAD')
+        return self.refs['HEAD']
 
     def _get_object(self, sha, cls):
         assert len(sha) in (20, 40)
         ret = self.get_object(sha)
-        if ret._type != cls._type:
+        if not isinstance(ret, cls):
             if cls is Commit:
                 raise NotCommitError(ret)
             elif cls is Blob:
                 raise NotBlobError(ret)
             elif cls is Tree:
                 raise NotTreeError(ret)
+            elif cls is Tag:
+                raise NotTagError(ret)
             else:
-                raise Exception("Type invalid: %r != %r" % (ret._type, cls._type))
+                raise Exception("Type invalid: %r != %r" % (
+                  ret.type_name, cls.type_name))
         return ret
 
     def get_object(self, sha):
@@ -340,18 +883,74 @@
     def get_parents(self, sha):
         return self.commit(sha).parents
 
+    def get_config(self):
+        import ConfigParser
+        p = ConfigParser.RawConfigParser()
+        p.read(os.path.join(self._controldir, 'config'))
+        return dict((section, dict(p.items(section)))
+                    for section in p.sections())
+
     def commit(self, sha):
+        """Retrieve the commit with a particular SHA.
+
+        :param sha: SHA of the commit to retrieve
+        :raise NotCommitError: If the SHA provided doesn't point at a Commit
+        :raise KeyError: If the SHA provided didn't exist
+        :return: A `Commit` object
+        """
+        warnings.warn("Repo.commit(sha) is deprecated. Use Repo[sha] instead.",
+            category=DeprecationWarning, stacklevel=2)
         return self._get_object(sha, Commit)
 
     def tree(self, sha):
+        """Retrieve the tree with a particular SHA.
+
+        :param sha: SHA of the tree to retrieve
+        :raise NotTreeError: If the SHA provided doesn't point at a Tree
+        :raise KeyError: If the SHA provided didn't exist
+        :return: A `Tree` object
+        """
+        warnings.warn("Repo.tree(sha) is deprecated. Use Repo[sha] instead.",
+            category=DeprecationWarning, stacklevel=2)
         return self._get_object(sha, Tree)
 
     def tag(self, sha):
+        """Retrieve the tag with a particular SHA.
+
+        :param sha: SHA of the tag to retrieve
+        :raise NotTagError: If the SHA provided doesn't point at a Tag
+        :raise KeyError: If the SHA provided didn't exist
+        :return: A `Tag` object
+        """
+        warnings.warn("Repo.tag(sha) is deprecated. Use Repo[sha] instead.",
+            category=DeprecationWarning, stacklevel=2)
         return self._get_object(sha, Tag)
 
     def get_blob(self, sha):
+        """Retrieve the blob with a particular SHA.
+
+        :param sha: SHA of the blob to retrieve
+        :raise NotBlobError: If the SHA provided doesn't point at a Blob
+        :raise KeyError: If the SHA provided didn't exist
+        :return: A `Blob` object
+        """
+        warnings.warn("Repo.get_blob(sha) is deprecated. Use Repo[sha] "
+            "instead.", category=DeprecationWarning, stacklevel=2)
         return self._get_object(sha, Blob)
 
+    def get_peeled(self, ref):
+        """Get the peeled value of a ref.
+
+        :param ref: The refname to peel.
+        :return: The fully-peeled SHA1 of a tag object, after peeling all
+            intermediate tags; if the original ref does not point to a tag, this
+            will equal the original SHA1.
+        """
+        cached = self.refs.get_peeled(ref)
+        if cached is not None:
+            return cached
+        return self.object_store.peel_sha(self.refs[ref]).id
+
     def revision_history(self, head):
         """Returns a list of the commits reachable from head.
 
@@ -370,9 +969,11 @@
         while pending_commits != []:
             head = pending_commits.pop(0)
             try:
-                commit = self.commit(head)
+                commit = self[head]
             except KeyError:
                 raise MissingCommitError(head)
+            if type(commit) != Commit:
+                raise NotCommitError(commit)
             if commit in history:
                 continue
             i = 0
@@ -381,19 +982,27 @@
                     break
                 i += 1
             history.insert(i, commit)
-            parents = commit.parents
-            pending_commits += parents
+            pending_commits += commit.parents
         history.reverse()
         return history
 
-    def __repr__(self):
-        return "<Repo at %r>" % self.path
-
     def __getitem__(self, name):
         if len(name) in (20, 40):
-            return self.object_store[name]
-        return self.object_store[self.refs[name]]
-    
+            try:
+                return self.object_store[name]
+            except KeyError:
+                pass
+        try:
+            return self.object_store[self.refs[name]]
+        except RefFormatError:
+            raise KeyError(name)
+
+    def __contains__(self, name):
+        if len(name) in (20, 40):
+            return name in self.object_store or name in self.refs
+        else:
+            return name in self.refs
+
     def __setitem__(self, name, value):
         if name.startswith("refs/") or name == "HEAD":
             if isinstance(value, ShaFile):
@@ -402,43 +1011,51 @@
                 self.refs[name] = value
             else:
                 raise TypeError(value)
-        raise ValueError(name)
+        else:
+            raise ValueError(name)
 
     def __delitem__(self, name):
         if name.startswith("refs") or name == "HEAD":
             del self.refs[name]
         raise ValueError(name)
 
-    def do_commit(self, committer, message,
+    def do_commit(self, message, committer=None,
                   author=None, commit_timestamp=None,
-                  commit_timezone=None, author_timestamp=None, 
-                  author_timezone=None, tree=None):
+                  commit_timezone=None, author_timestamp=None,
+                  author_timezone=None, tree=None, encoding=None):
         """Create a new commit.
 
+        :param message: Commit message
         :param committer: Committer fullname
-        :param message: Commit message
         :param author: Author fullname (defaults to committer)
         :param commit_timestamp: Commit timestamp (defaults to now)
         :param commit_timezone: Commit timestamp timezone (defaults to GMT)
         :param author_timestamp: Author timestamp (defaults to commit timestamp)
-        :param author_timezone: Author timestamp timezone 
+        :param author_timezone: Author timestamp timezone
             (defaults to commit timestamp timezone)
-        :param tree: SHA1 of the tree root to use (if not specified the current index will be committed).
+        :param tree: SHA1 of the tree root to use (if not specified the
+            current index will be committed).
+        :param encoding: Encoding
         :return: New commit SHA1
         """
-        from dulwich.index import commit_index
         import time
-        index = self.open_index()
         c = Commit()
         if tree is None:
-            c.tree = commit_index(self.object_store, index)
+            index = self.open_index()
+            c.tree = index.commit(self.object_store)
         else:
+            if len(tree) != 40:
+                raise ValueError("tree must be a 40-byte hex sha string")
             c.tree = tree
+        # TODO: Allow username to be missing, and get it from .git/config
+        if committer is None:
+            raise ValueError("committer not set")
         c.committer = committer
         if commit_timestamp is None:
             commit_timestamp = time.time()
         c.commit_time = int(commit_timestamp)
         if commit_timezone is None:
+            # FIXME: Use current user timezone rather than UTC
             commit_timezone = 0
         c.commit_timezone = commit_timezone
         if author is None:
@@ -450,35 +1067,204 @@
         if author_timezone is None:
             author_timezone = commit_timezone
         c.author_timezone = author_timezone
+        if encoding is not None:
+            c.encoding = encoding
         c.message = message
-        self.object_store.add_object(c)
-        self.refs["HEAD"] = c.id
+        try:
+            old_head = self.refs["HEAD"]
+            c.parents = [old_head]
+            self.object_store.add_object(c)
+            ok = self.refs.set_if_equals("HEAD", old_head, c.id)
+        except KeyError:
+            c.parents = []
+            self.object_store.add_object(c)
+            ok = self.refs.add_if_new("HEAD", c.id)
+        if not ok:
+            # Fail if the atomic compare-and-swap failed, leaving the commit and
+            # all its objects as garbage.
+            raise CommitError("HEAD changed during commit")
+
         return c.id
 
-    @classmethod
-    def init(cls, path, mkdir=True):
+
+class Repo(BaseRepo):
+    """A git repository backed by local disk."""
+
+    def __init__(self, root):
+        if os.path.isdir(os.path.join(root, ".git", OBJECTDIR)):
+            self.bare = False
+            self._controldir = os.path.join(root, ".git")
+        elif (os.path.isdir(os.path.join(root, OBJECTDIR)) and
+              os.path.isdir(os.path.join(root, REFSDIR))):
+            self.bare = True
+            self._controldir = root
+        else:
+            raise NotGitRepository(root)
+        self.path = root
+        object_store = DiskObjectStore(os.path.join(self.controldir(),
+                                                    OBJECTDIR))
+        refs = DiskRefsContainer(self.controldir())
+        BaseRepo.__init__(self, object_store, refs)
+
+    def controldir(self):
+        """Return the path of the control directory."""
+        return self._controldir
+
+    def _put_named_file(self, path, contents):
+        """Write a file to the control dir with the given name and contents.
+
+        :param path: The path to the file, relative to the control dir.
+        :param contents: A string to write to the file.
+        """
+        path = path.lstrip(os.path.sep)
+        f = GitFile(os.path.join(self.controldir(), path), 'wb')
+        try:
+            f.write(contents)
+        finally:
+            f.close()
+
+    def get_named_file(self, path):
+        """Get a file from the control dir with a specific name.
+
+        Although the filename should be interpreted as a filename relative to
+        the control dir in a disk-based Repo, the object returned need not be
+        pointing to a file in that location.
+
+        :param path: The path to the file, relative to the control dir.
+        :return: An open file object, or None if the file does not exist.
+        """
+        # TODO(dborowitz): sanitize filenames, since this is used directly by
+        # the dumb web serving code.
+        path = path.lstrip(os.path.sep)
+        try:
+            return open(os.path.join(self.controldir(), path), 'rb')
+        except (IOError, OSError), e:
+            if e.errno == errno.ENOENT:
+                return None
+            raise
+
+    def index_path(self):
+        """Return path to the index file."""
+        return os.path.join(self.controldir(), INDEX_FILENAME)
+
+    def open_index(self):
+        """Open the index for this repository."""
+        from dulwich.index import Index
+        if not self.has_index():
+            raise NoIndexPresent()
+        return Index(self.index_path())
+
+    def has_index(self):
+        """Check if an index is present."""
+        # Bare repos must never have index files; non-bare repos may have a
+        # missing index file, which is treated as empty.
+        return not self.bare
+
+    def stage(self, paths):
+        """Stage a set of paths.
+
+        :param paths: List of paths, relative to the repository path
+        """
+        from dulwich.index import cleanup_mode
+        index = self.open_index()
+        for path in paths:
+            full_path = os.path.join(self.path, path)
+            blob = Blob()
+            try:
+                st = os.stat(full_path)
+            except OSError:
+                # File no longer exists
+                try:
+                    del index[path]
+                except KeyError:
+                    pass  # Doesn't exist in the index either
+            else:
+                f = open(full_path, 'rb')
+                try:
+                    blob.data = f.read()
+                finally:
+                    f.close()
+                self.object_store.add_object(blob)
+                # XXX: Cleanup some of the other file properties as well?
+                index[path] = (st.st_ctime, st.st_mtime, st.st_dev, st.st_ino,
+                    cleanup_mode(st.st_mode), st.st_uid, st.st_gid, st.st_size,
+                    blob.id, 0)
+        index.write()
+
+    def __repr__(self):
+        return "<Repo at %r>" % self.path
+
+    @classmethod
+    def _init_maybe_bare(cls, path, bare):
+        for d in BASE_DIRECTORIES:
+            os.mkdir(os.path.join(path, *d))
+        DiskObjectStore.init(os.path.join(path, OBJECTDIR))
+        ret = cls(path)
+        ret.refs.set_symbolic_ref("HEAD", "refs/heads/master")
+        ret._init_files(bare)
+        return ret
+
+    @classmethod
+    def init(cls, path, mkdir=False):
+        if mkdir:
+            os.mkdir(path)
         controldir = os.path.join(path, ".git")
         os.mkdir(controldir)
-        cls.init_bare(controldir)
+        cls._init_maybe_bare(controldir, False)
         return cls(path)
 
     @classmethod
-    def init_bare(cls, path, mkdir=True):
-        for d in [[OBJECTDIR], 
-                  [OBJECTDIR, "info"], 
-                  [OBJECTDIR, "pack"],
-                  ["branches"],
-                  [REFSDIR],
-                  [REFSDIR, REFSDIR_TAGS],
-                  [REFSDIR, REFSDIR_HEADS],
-                  ["hooks"],
-                  ["info"]]:
-            os.mkdir(os.path.join(path, *d))
-        ret = cls(path)
-        ret.refs.set_ref("HEAD", "refs/heads/master")
-        open(os.path.join(path, 'description'), 'wb').write("Unnamed repository")
-        open(os.path.join(path, 'info', 'excludes'), 'wb').write("")
-        return ret
+    def init_bare(cls, path):
+        return cls._init_maybe_bare(path, True)
 
     create = init_bare
 
+
+class MemoryRepo(BaseRepo):
+    """Repo that stores refs, objects, and named files in memory.
+
+    MemoryRepos are always bare: they have no working tree and no index, since
+    those have a stronger dependency on the filesystem.
+    """
+
+    def __init__(self):
+        BaseRepo.__init__(self, MemoryObjectStore(), DictRefsContainer({}))
+        self._named_files = {}
+        self.bare = True
+
+    def _put_named_file(self, path, contents):
+        """Write a file to the control dir with the given name and contents.
+
+        :param path: The path to the file, relative to the control dir.
+        :param contents: A string to write to the file.
+        """
+        self._named_files[path] = contents
+
+    def get_named_file(self, path):
+        """Get a file from the control dir with a specific name.
+
+        Although the filename should be interpreted as a filename relative to
+        the control dir in a disk-baked Repo, the object returned need not be
+        pointing to a file in that location.
+
+        :param path: The path to the file, relative to the control dir.
+        :return: An open file object, or None if the file does not exist.
+        """
+        contents = self._named_files.get(path, None)
+        if contents is None:
+            return None
+        return StringIO(contents)
+
+    def open_index(self):
+        """Fail to open index for this repo, since it is bare."""
+        raise NoIndexPresent()
+
+    @classmethod
+    def init_bare(cls, objects, refs):
+        ret = cls()
+        for obj in objects:
+            ret.object_store.add_object(obj)
+        for refname, sha in refs.iteritems():
+            ret.refs[refname] = sha
+        ret._init_files(bare=True)
+        return ret

=== modified file 'dulwich/server.py'
--- dulwich/server.py	2009-09-10 12:30:34 +0000
+++ dulwich/server.py	2010-12-25 22:24:59 +0000
@@ -1,5 +1,5 @@
 # server.py -- Implementation of the server side git protocols
-# Copryight (C) 2008 John Carr <john.carr@xxxxxxxxxxxxxx>
+# Copyright (C) 2008 John Carr <john.carr@xxxxxxxxxxxxxx>
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -16,27 +16,76 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
-
-"""Git smart network protocol server implementation."""
-
-
+"""Git smart network protocol server implementation.
+
+For more detailed implementation on the network protocol, see the
+Documentation/technical directory in the cgit distribution, and in particular:
+
+* Documentation/technical/protocol-capabilities.txt
+* Documentation/technical/pack-protocol.txt
+"""
+
+
+import collections
+import socket
 import SocketServer
-import tempfile
+import sys
+import zlib
 
+from dulwich.errors import (
+    ApplyDeltaError,
+    ChecksumMismatch,
+    GitProtocolError,
+    UnexpectedCommandError,
+    ObjectFormatException,
+    )
+from dulwich import log_utils
+from dulwich.objects import (
+    hex_to_sha,
+    )
+from dulwich.pack import (
+    PackStreamReader,
+    write_pack_data,
+    )
 from dulwich.protocol import (
+    BufferedPktLineWriter,
+    MULTI_ACK,
+    MULTI_ACK_DETAILED,
     Protocol,
     ProtocolFile,
+    ReceivableProtocol,
+    SINGLE_ACK,
     TCP_GIT_PORT,
+    ZERO_SHA,
+    ack_type,
     extract_capabilities,
+    extract_want_line_capabilities,
     )
 from dulwich.repo import (
     Repo,
     )
-from dulwich.pack import (
-    write_pack_data,
-    )
+
+
+logger = log_utils.getLogger(__name__)
+
 
 class Backend(object):
+    """A backend for the Git smart server implementation."""
+
+    def open_repository(self, path):
+        """Open the repository at a path."""
+        raise NotImplementedError(self.open_repository)
+
+
+class BackendRepo(object):
+    """Repository abstraction used by the Git server.
+    
+    Please note that the methods required here are a 
+    subset of those provided by dulwich.repo.Repo.
+    """
+
+    object_store = None
+    refs = None
 
     def get_refs(self):
         """
@@ -46,178 +95,608 @@
         """
         raise NotImplementedError
 
-    def apply_pack(self, refs, read):
-        """ Import a set of changes into a repository and update the refs
+    def get_peeled(self, name):
+        """Return the cached peeled value of a ref, if available.
 
-        :param refs: list of tuple(name, sha)
-        :param read: callback to read from the incoming pack
+        :param name: Name of the ref to peel
+        :return: The peeled value of the ref. If the ref is known not point to
+            a tag, this will be the SHA the ref refers to. If no cached
+            information about a tag is available, this method may return None,
+            but it should attempt to peel the tag if possible.
         """
-        raise NotImplementedError
+        return None
 
-    def fetch_objects(self, determine_wants, graph_walker, progress):
+    def fetch_objects(self, determine_wants, graph_walker, progress,
+                      get_tagged=None):
         """
         Yield the objects required for a list of commits.
 
         :param progress: is a callback to send progress messages to the client
+        :param get_tagged: Function that returns a dict of pointed-to sha -> tag
+            sha for including tags.
         """
         raise NotImplementedError
 
 
-class GitBackend(Backend):
-
-    def __init__(self, gitdir=None):
-        self.gitdir = gitdir
-
-        if not self.gitdir:
-            self.gitdir = tempfile.mkdtemp()
-            Repo.create(self.gitdir)
-
-        self.repo = Repo(self.gitdir)
-        self.fetch_objects = self.repo.fetch_objects
-        self.get_refs = self.repo.get_refs
-
-    def apply_pack(self, refs, read):
-        f, commit = self.repo.object_store.add_thin_pack()
-        try:
-            f.write(read())
-        finally:
-            commit()
-
-        for oldsha, sha, ref in refs:
-            if ref == "0" * 40:
-                del self.repo.refs[ref]
-            else:
-                self.repo.refs[ref] = sha
-
-        print "pack applied"
+class PackStreamCopier(PackStreamReader):
+    """Class to verify a pack stream as it is being read.
+
+    The pack is read from a ReceivableProtocol using read() or recv() as
+    appropriate and written out to the given file-like object.
+    """
+
+    def __init__(self, read_all, read_some, outfile):
+        super(PackStreamCopier, self).__init__(read_all, read_some)
+        self.outfile = outfile
+
+    def _read(self, read, size):
+        data = super(PackStreamCopier, self)._read(read, size)
+        self.outfile.write(data)
+        return data
+
+    def verify(self):
+        """Verify a pack stream and write it to the output file.
+
+        See PackStreamReader.iterobjects for a list of exceptions this may
+        throw.
+        """
+        for _, _, _ in self.read_objects():
+            pass
+
+
+class DictBackend(Backend):
+    """Trivial backend that looks up Git repositories in a dictionary."""
+
+    def __init__(self, repos):
+        self.repos = repos
+
+    def open_repository(self, path):
+        logger.debug('Opening repository at %s', path)
+        # FIXME: What to do in case there is no repo ?
+        return self.repos[path]
+
+
+class FileSystemBackend(Backend):
+    """Simple backend that looks up Git repositories in the local file system."""
+
+    def open_repository(self, path):
+        logger.debug('opening repository at %s', path)
+        return Repo(path)
 
 
 class Handler(object):
     """Smart protocol command handler base class."""
 
-    def __init__(self, backend, read, write):
+    def __init__(self, backend, proto):
         self.backend = backend
-        self.proto = Protocol(read, write)
-
-    def capabilities(self):
-        return " ".join(self.default_capabilities())
+        self.proto = proto
+        self._client_capabilities = None
+
+    @classmethod
+    def capability_line(cls):
+        return " ".join(cls.capabilities())
+
+    @classmethod
+    def capabilities(cls):
+        raise NotImplementedError(cls.capabilities)
+
+    @classmethod
+    def innocuous_capabilities(cls):
+        return ("include-tag", "thin-pack", "no-progress", "ofs-delta")
+
+    @classmethod
+    def required_capabilities(cls):
+        """Return a list of capabilities that we require the client to have."""
+        return []
+
+    def set_client_capabilities(self, caps):
+        allowable_caps = set(self.innocuous_capabilities())
+        allowable_caps.update(self.capabilities())
+        for cap in caps:
+            if cap not in allowable_caps:
+                raise GitProtocolError('Client asked for capability %s that '
+                                       'was not advertised.' % cap)
+        for cap in self.required_capabilities():
+            if cap not in caps:
+                raise GitProtocolError('Client does not support required '
+                                       'capability %s.' % cap)
+        self._client_capabilities = set(caps)
+        logger.info('Client capabilities: %s', caps)
+
+    def has_capability(self, cap):
+        if self._client_capabilities is None:
+            raise GitProtocolError('Server attempted to access capability %s '
+                                   'before asking client' % cap)
+        return cap in self._client_capabilities
 
 
 class UploadPackHandler(Handler):
     """Protocol handler for uploading a pack to the server."""
 
-    def default_capabilities(self):
-        return ("multi_ack", "side-band-64k", "thin-pack", "ofs-delta")
+    def __init__(self, backend, args, proto,
+                 stateless_rpc=False, advertise_refs=False):
+        Handler.__init__(self, backend, proto)
+        self.repo = backend.open_repository(args[0])
+        self._graph_walker = None
+        self.stateless_rpc = stateless_rpc
+        self.advertise_refs = advertise_refs
+
+    @classmethod
+    def capabilities(cls):
+        return ("multi_ack_detailed", "multi_ack", "side-band-64k", "thin-pack",
+                "ofs-delta", "no-progress", "include-tag")
+
+    @classmethod
+    def required_capabilities(cls):
+        return ("side-band-64k", "thin-pack", "ofs-delta")
+
+    def progress(self, message):
+        if self.has_capability("no-progress"):
+            return
+        self.proto.write_sideband(2, message)
+
+    def get_tagged(self, refs=None, repo=None):
+        """Get a dict of peeled values of tags to their original tag shas.
+
+        :param refs: dict of refname -> sha of possible tags; defaults to all of
+            the backend's refs.
+        :param repo: optional Repo instance for getting peeled refs; defaults to
+            the backend's repo, if available
+        :return: dict of peeled_sha -> tag_sha, where tag_sha is the sha of a
+            tag whose peeled value is peeled_sha.
+        """
+        if not self.has_capability("include-tag"):
+            return {}
+        if refs is None:
+            refs = self.repo.get_refs()
+        if repo is None:
+            repo = getattr(self.repo, "repo", None)
+            if repo is None:
+                # Bail if we don't have a Repo available; this is ok since
+                # clients must be able to handle if the server doesn't include
+                # all relevant tags.
+                # TODO: fix behavior when missing
+                return {}
+        tagged = {}
+        for name, sha in refs.iteritems():
+            peeled_sha = repo.get_peeled(name)
+            if peeled_sha != sha:
+                tagged[peeled_sha] = sha
+        return tagged
 
     def handle(self):
-        def determine_wants(heads):
-            keys = heads.keys()
-            if keys:
-                self.proto.write_pkt_line("%s %s\x00%s\n" % ( heads[keys[0]], keys[0], self.capabilities()))
-                for k in keys[1:]:
-                    self.proto.write_pkt_line("%s %s\n" % (heads[k], k))
-
-            # i'm done..
-            self.proto.write("0000")
-
-            # Now client will either send "0000", meaning that it doesnt want to pull.
-            # or it will start sending want want want commands
-            want = self.proto.read_pkt_line()
-            if want == None:
-                return []
-
-            want, self.client_capabilities = extract_capabilities(want)
-
-            want_revs = []
-            while want and want[:4] == 'want':
-                want_revs.append(want[5:45])
-                want = self.proto.read_pkt_line()
-                if want == None:
-                    self.proto.write_pkt_line("ACK %s\n" % want_revs[-1])
-            return want_revs
-
-        progress = lambda x: self.proto.write_sideband(2, x)
         write = lambda x: self.proto.write_sideband(1, x)
 
-        class ProtocolGraphWalker(object):
-
-            def __init__(self, proto):
-                self.proto = proto
-                self._last_sha = None
-                self._cached = False
-                self._cache = []
-                self._cache_index = 0
-
-            def ack(self, have_ref):
-                self.proto.write_pkt_line("ACK %s continue\n" % have_ref)
-
-            def reset(self):
-                self._cached = True
-                self._cache_index = 0
-
-            def next(self):
-                if not self._cached:
-                    return self.next_from_proto()
-                self._cache_index = self._cache_index + 1
-                if self._cache_index > len(self._cache):
-                    return None
-                return self._cache[self._cache_index]
-
-            def next_from_proto(self):
-                have = self.proto.read_pkt_line()
-                if have is None:
-                    self.proto.write_pkt_line("ACK %s\n" % self._last_sha)
-                    return None
-
-                if have[:4] == 'have':
-                    self._cache.append(have[5:45])
-                    return have[5:45]
-
-
-                #if have[:4] == 'done':
-                #    return None
-
-                if self._last_sha:
-                    # Oddness: Git seems to resend the last ACK, without the "continue" statement
-                    self.proto.write_pkt_line("ACK %s\n" % self._last_sha)
-
-                # The exchange finishes with a NAK
-                self.proto.write_pkt_line("NAK\n")
-
-        graph_walker = ProtocolGraphWalker(self.proto)
-        objects_iter = self.backend.fetch_objects(determine_wants, graph_walker, progress)
-
-        # Do they want any objects?
-        if len(objects_iter) == 0:
+        graph_walker = ProtocolGraphWalker(self, self.repo.object_store,
+            self.repo.get_peeled)
+        objects_iter = self.repo.fetch_objects(
+          graph_walker.determine_wants, graph_walker, self.progress,
+          get_tagged=self.get_tagged)
+
+        # Did the process short-circuit (e.g. in a stateless RPC call)? Note
+        # that the client still expects a 0-object pack in most cases.
+        if objects_iter is None:
             return
 
-        progress("dul-daemon says what\n")
-        progress("counting objects: %d, done.\n" % len(objects_iter))
+        self.progress("dul-daemon says what\n")
+        self.progress("counting objects: %d, done.\n" % len(objects_iter))
         write_pack_data(ProtocolFile(None, write), objects_iter, 
                         len(objects_iter))
-        progress("how was that, then?\n")
+        self.progress("how was that, then?\n")
         # we are done
         self.proto.write("0000")
 
 
+def _split_proto_line(line, allowed):
+    """Split a line read from the wire.
+
+    :param line: The line read from the wire.
+    :param allowed: An iterable of command names that should be allowed.
+        Command names not listed below as possible return values will be
+        ignored.  If None, any commands from the possible return values are
+        allowed.
+    :return: a tuple having one of the following forms:
+        ('want', obj_id)
+        ('have', obj_id)
+        ('done', None)
+        (None, None)  (for a flush-pkt)
+
+    :raise UnexpectedCommandError: if the line cannot be parsed into one of the
+        allowed return values.
+    """
+    if not line:
+        fields = [None]
+    else:
+        fields = line.rstrip('\n').split(' ', 1)
+    command = fields[0]
+    if allowed is not None and command not in allowed:
+        raise UnexpectedCommandError(command)
+    try:
+        if len(fields) == 1 and command in ('done', None):
+            return (command, None)
+        elif len(fields) == 2 and command in ('want', 'have'):
+            hex_to_sha(fields[1])
+            return tuple(fields)
+    except (TypeError, AssertionError), e:
+        raise GitProtocolError(e)
+    raise GitProtocolError('Received invalid line from client: %s' % line)
+
+
+class ProtocolGraphWalker(object):
+    """A graph walker that knows the git protocol.
+
+    As a graph walker, this class implements ack(), next(), and reset(). It
+    also contains some base methods for interacting with the wire and walking
+    the commit tree.
+
+    The work of determining which acks to send is passed on to the
+    implementation instance stored in _impl. The reason for this is that we do
+    not know at object creation time what ack level the protocol requires. A
+    call to set_ack_level() is required to set up the implementation, before any
+    calls to next() or ack() are made.
+    """
+    def __init__(self, handler, object_store, get_peeled):
+        self.handler = handler
+        self.store = object_store
+        self.get_peeled = get_peeled
+        self.proto = handler.proto
+        self.stateless_rpc = handler.stateless_rpc
+        self.advertise_refs = handler.advertise_refs
+        self._wants = []
+        self._cached = False
+        self._cache = []
+        self._cache_index = 0
+        self._impl = None
+
+    def determine_wants(self, heads):
+        """Determine the wants for a set of heads.
+
+        The given heads are advertised to the client, who then specifies which
+        refs he wants using 'want' lines. This portion of the protocol is the
+        same regardless of ack type, and in fact is used to set the ack type of
+        the ProtocolGraphWalker.
+
+        :param heads: a dict of refname->SHA1 to advertise
+        :return: a list of SHA1s requested by the client
+        """
+        if not heads:
+            raise GitProtocolError('No heads found')
+        values = set(heads.itervalues())
+        if self.advertise_refs or not self.stateless_rpc:
+            for i, (ref, sha) in enumerate(heads.iteritems()):
+                line = "%s %s" % (sha, ref)
+                if not i:
+                    line = "%s\x00%s" % (line, self.handler.capability_line())
+                self.proto.write_pkt_line("%s\n" % line)
+                peeled_sha = self.get_peeled(ref)
+                if peeled_sha != sha:
+                    self.proto.write_pkt_line('%s %s^{}\n' %
+                                              (peeled_sha, ref))
+
+            # i'm done..
+            self.proto.write_pkt_line(None)
+
+            if self.advertise_refs:
+                return None
+
+        # Now client will sending want want want commands
+        want = self.proto.read_pkt_line()
+        if not want:
+            return []
+        line, caps = extract_want_line_capabilities(want)
+        self.handler.set_client_capabilities(caps)
+        self.set_ack_type(ack_type(caps))
+        allowed = ('want', None)
+        command, sha = _split_proto_line(line, allowed)
+
+        want_revs = []
+        while command != None:
+            if sha not in values:
+                raise GitProtocolError(
+                  'Client wants invalid object %s' % sha)
+            want_revs.append(sha)
+            command, sha = self.read_proto_line(allowed)
+
+        self.set_wants(want_revs)
+
+        if self.stateless_rpc and self.proto.eof():
+            # The client may close the socket at this point, expecting a
+            # flush-pkt from the server. We might be ready to send a packfile at
+            # this point, so we need to explicitly short-circuit in this case.
+            return None
+
+        return want_revs
+
+    def ack(self, have_ref):
+        return self._impl.ack(have_ref)
+
+    def reset(self):
+        self._cached = True
+        self._cache_index = 0
+
+    def next(self):
+        if not self._cached:
+            if not self._impl and self.stateless_rpc:
+                return None
+            return self._impl.next()
+        self._cache_index += 1
+        if self._cache_index > len(self._cache):
+            return None
+        return self._cache[self._cache_index]
+
+    def read_proto_line(self, allowed):
+        """Read a line from the wire.
+
+        :param allowed: An iterable of command names that should be allowed.
+        :return: A tuple of (command, value); see _split_proto_line.
+        :raise GitProtocolError: If an error occurred reading the line.
+        """
+        return _split_proto_line(self.proto.read_pkt_line(), allowed)
+
+    def send_ack(self, sha, ack_type=''):
+        if ack_type:
+            ack_type = ' %s' % ack_type
+        self.proto.write_pkt_line('ACK %s%s\n' % (sha, ack_type))
+
+    def send_nak(self):
+        self.proto.write_pkt_line('NAK\n')
+
+    def set_wants(self, wants):
+        self._wants = wants
+
+    def _is_satisfied(self, haves, want, earliest):
+        """Check whether a want is satisfied by a set of haves.
+
+        A want, typically a branch tip, is "satisfied" only if there exists a
+        path back from that want to one of the haves.
+
+        :param haves: A set of commits we know the client has.
+        :param want: The want to check satisfaction for.
+        :param earliest: A timestamp beyond which the search for haves will be
+            terminated, presumably because we're searching too far down the
+            wrong branch.
+        """
+        o = self.store[want]
+        pending = collections.deque([o])
+        while pending:
+            commit = pending.popleft()
+            if commit.id in haves:
+                return True
+            if commit.type_name != "commit":
+                # non-commit wants are assumed to be satisfied
+                continue
+            for parent in commit.parents:
+                parent_obj = self.store[parent]
+                # TODO: handle parents with later commit times than children
+                if parent_obj.commit_time >= earliest:
+                    pending.append(parent_obj)
+        return False
+
+    def all_wants_satisfied(self, haves):
+        """Check whether all the current wants are satisfied by a set of haves.
+
+        :param haves: A set of commits we know the client has.
+        :note: Wants are specified with set_wants rather than passed in since
+            in the current interface they are determined outside this class.
+        """
+        haves = set(haves)
+        earliest = min([self.store[h].commit_time for h in haves])
+        for want in self._wants:
+            if not self._is_satisfied(haves, want, earliest):
+                return False
+        return True
+
+    def set_ack_type(self, ack_type):
+        impl_classes = {
+          MULTI_ACK: MultiAckGraphWalkerImpl,
+          MULTI_ACK_DETAILED: MultiAckDetailedGraphWalkerImpl,
+          SINGLE_ACK: SingleAckGraphWalkerImpl,
+          }
+        self._impl = impl_classes[ack_type](self)
+
+
+_GRAPH_WALKER_COMMANDS = ('have', 'done', None)
+
+
+class SingleAckGraphWalkerImpl(object):
+    """Graph walker implementation that speaks the single-ack protocol."""
+
+    def __init__(self, walker):
+        self.walker = walker
+        self._sent_ack = False
+
+    def ack(self, have_ref):
+        if not self._sent_ack:
+            self.walker.send_ack(have_ref)
+            self._sent_ack = True
+
+    def next(self):
+        command, sha = self.walker.read_proto_line(_GRAPH_WALKER_COMMANDS)
+        if command in (None, 'done'):
+            if not self._sent_ack:
+                self.walker.send_nak()
+            return None
+        elif command == 'have':
+            return sha
+
+
+class MultiAckGraphWalkerImpl(object):
+    """Graph walker implementation that speaks the multi-ack protocol."""
+
+    def __init__(self, walker):
+        self.walker = walker
+        self._found_base = False
+        self._common = []
+
+    def ack(self, have_ref):
+        self._common.append(have_ref)
+        if not self._found_base:
+            self.walker.send_ack(have_ref, 'continue')
+            if self.walker.all_wants_satisfied(self._common):
+                self._found_base = True
+        # else we blind ack within next
+
+    def next(self):
+        while True:
+            command, sha = self.walker.read_proto_line(_GRAPH_WALKER_COMMANDS)
+            if command is None:
+                self.walker.send_nak()
+                # in multi-ack mode, a flush-pkt indicates the client wants to
+                # flush but more have lines are still coming
+                continue
+            elif command == 'done':
+                # don't nak unless no common commits were found, even if not
+                # everything is satisfied
+                if self._common:
+                    self.walker.send_ack(self._common[-1])
+                else:
+                    self.walker.send_nak()
+                return None
+            elif command == 'have':
+                if self._found_base:
+                    # blind ack
+                    self.walker.send_ack(sha, 'continue')
+                return sha
+
+
+class MultiAckDetailedGraphWalkerImpl(object):
+    """Graph walker implementation speaking the multi-ack-detailed protocol."""
+
+    def __init__(self, walker):
+        self.walker = walker
+        self._found_base = False
+        self._common = []
+
+    def ack(self, have_ref):
+        self._common.append(have_ref)
+        if not self._found_base:
+            self.walker.send_ack(have_ref, 'common')
+            if self.walker.all_wants_satisfied(self._common):
+                self._found_base = True
+                self.walker.send_ack(have_ref, 'ready')
+        # else we blind ack within next
+
+    def next(self):
+        while True:
+            command, sha = self.walker.read_proto_line(_GRAPH_WALKER_COMMANDS)
+            if command is None:
+                self.walker.send_nak()
+                if self.walker.stateless_rpc:
+                    return None
+                continue
+            elif command == 'done':
+                # don't nak unless no common commits were found, even if not
+                # everything is satisfied
+                if self._common:
+                    self.walker.send_ack(self._common[-1])
+                else:
+                    self.walker.send_nak()
+                return None
+            elif command == 'have':
+                if self._found_base:
+                    # blind ack; can happen if the client has more requests
+                    # inflight
+                    self.walker.send_ack(sha, 'ready')
+                return sha
+
+
 class ReceivePackHandler(Handler):
-    """Protocol handler for downloading a pack to the client."""
-
-    def default_capabilities(self):
-        return ("report-status", "delete-refs")
+    """Protocol handler for downloading a pack from the client."""
+
+    def __init__(self, backend, args, proto,
+                 stateless_rpc=False, advertise_refs=False):
+        Handler.__init__(self, backend, proto)
+        self.repo = backend.open_repository(args[0])
+        self.stateless_rpc = stateless_rpc
+        self.advertise_refs = advertise_refs
+
+    @classmethod
+    def capabilities(cls):
+        return ("report-status", "delete-refs", "side-band-64k")
+
+    def _apply_pack(self, refs):
+        f, commit = self.repo.object_store.add_thin_pack()
+        all_exceptions = (IOError, OSError, ChecksumMismatch, ApplyDeltaError,
+                          AssertionError, socket.error, zlib.error,
+                          ObjectFormatException)
+        status = []
+        # TODO: more informative error messages than just the exception string
+        try:
+            PackStreamCopier(self.proto.read, self.proto.recv, f).verify()
+            p = commit()
+            if not p:
+                raise IOError('Failed to write pack')
+            p.check()
+            status.append(('unpack', 'ok'))
+        except all_exceptions, e:
+            status.append(('unpack', str(e).replace('\n', '')))
+            # The pack may still have been moved in, but it may contain broken
+            # objects. We trust a later GC to clean it up.
+
+        for oldsha, sha, ref in refs:
+            ref_status = 'ok'
+            try:
+                if sha == ZERO_SHA:
+                    if not 'delete-refs' in self.capabilities():
+                        raise GitProtocolError(
+                          'Attempted to delete refs without delete-refs '
+                          'capability.')
+                    try:
+                        del self.repo.refs[ref]
+                    except all_exceptions:
+                        ref_status = 'failed to delete'
+                else:
+                    try:
+                        self.repo.refs[ref] = sha
+                    except all_exceptions:
+                        ref_status = 'failed to write'
+            except KeyError, e:
+                ref_status = 'bad ref'
+            status.append((ref, ref_status))
+
+        return status
+
+    def _report_status(self, status):
+        if self.has_capability('side-band-64k'):
+            writer = BufferedPktLineWriter(
+              lambda d: self.proto.write_sideband(1, d))
+            write = writer.write
+
+            def flush():
+                writer.flush()
+                self.proto.write_pkt_line(None)
+        else:
+            write = self.proto.write_pkt_line
+            flush = lambda: None
+
+        for name, msg in status:
+            if name == 'unpack':
+                write('unpack %s\n' % msg)
+            elif msg == 'ok':
+                write('ok %s\n' % name)
+            else:
+                write('ng %s %s\n' % (name, msg))
+        write(None)
+        flush()
 
     def handle(self):
-        refs = self.backend.get_refs().items()
-
-        if refs:
-            self.proto.write_pkt_line("%s %s\x00%s\n" % (refs[0][1], refs[0][0], self.capabilities()))
-            for i in range(1, len(refs)):
-                ref = refs[i]
-                self.proto.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
-        else:
-            self.proto.write_pkt_line("0000000000000000000000000000000000000000 capabilities^{} %s" % self.capabilities())
-
-        self.proto.write("0000")
+        refs = self.repo.get_refs().items()
+
+        if self.advertise_refs or not self.stateless_rpc:
+            if refs:
+                self.proto.write_pkt_line(
+                  "%s %s\x00%s\n" % (refs[0][1], refs[0][0],
+                                     self.capability_line()))
+                for i in range(1, len(refs)):
+                    ref = refs[i]
+                    self.proto.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
+            else:
+                self.proto.write_pkt_line("%s capabilities^{} %s" % (
+                  ZERO_SHA, self.capability_line()))
+
+            self.proto.write("0000")
+            if self.advertise_refs:
+                return
 
         client_refs = []
         ref = self.proto.read_pkt_line()
@@ -226,7 +705,8 @@
         if ref is None:
             return
 
-        ref, client_capabilities = extract_capabilities(ref)
+        ref, caps = extract_capabilities(ref)
+        self.set_client_capabilities(caps)
 
         # client will now send us a list of (oldsha, newsha, ref)
         while ref:
@@ -234,28 +714,36 @@
             ref = self.proto.read_pkt_line()
 
         # backend can now deal with this refs and read a pack using self.read
-        self.backend.apply_pack(client_refs, self.proto.read)
-
-        # when we have read all the pack from the client, it assumes 
-        # everything worked OK.
-        # there is NO ack from the server before it reports victory.
+        status = self._apply_pack(client_refs)
+
+        # when we have read all the pack from the client, send a status report
+        # if the client asked for it
+        if self.has_capability('report-status'):
+            self._report_status(status)
+
+
+# Default handler classes for git services.
+DEFAULT_HANDLERS = {
+  'git-upload-pack': UploadPackHandler,
+  'git-receive-pack': ReceivePackHandler,
+  }
 
 
 class TCPGitRequestHandler(SocketServer.StreamRequestHandler):
 
+    def __init__(self, handlers, *args, **kwargs):
+        self.handlers = handlers
+        SocketServer.StreamRequestHandler.__init__(self, *args, **kwargs)
+
     def handle(self):
-        proto = Protocol(self.rfile.read, self.wfile.write)
+        proto = ReceivableProtocol(self.connection.recv, self.wfile.write)
         command, args = proto.read_cmd()
-
-        # switch case to handle the specific git command
-        if command == 'git-upload-pack':
-            cls = UploadPackHandler
-        elif command == 'git-receive-pack':
-            cls = ReceivePackHandler
-        else:
-            return
-
-        h = cls(self.server.backend, self.rfile.read, self.wfile.write)
+        logger.info('Handling %s request, args=%s', command, args)
+
+        cls = self.handlers.get(command, None)
+        if not callable(cls):
+            raise GitProtocolError('Invalid service %s' % command)
+        h = cls(self.server.backend, args, proto)
         h.handle()
 
 
@@ -264,8 +752,60 @@
     allow_reuse_address = True
     serve = SocketServer.TCPServer.serve_forever
 
-    def __init__(self, backend, listen_addr, port=TCP_GIT_PORT):
+    def _make_handler(self, *args, **kwargs):
+        return TCPGitRequestHandler(self.handlers, *args, **kwargs)
+
+    def __init__(self, backend, listen_addr, port=TCP_GIT_PORT, handlers=None):
+        self.handlers = dict(DEFAULT_HANDLERS)
+        if handlers is not None:
+            self.handlers.update(handlers)
         self.backend = backend
-        SocketServer.TCPServer.__init__(self, (listen_addr, port), TCPGitRequestHandler)
-
-
+        logger.info('Listening for TCP connections on %s:%d', listen_addr, port)
+        SocketServer.TCPServer.__init__(self, (listen_addr, port),
+                                        self._make_handler)
+
+    def verify_request(self, request, client_address):
+        logger.info('Handling request from %s', client_address)
+        return True
+
+    def handle_error(self, request, client_address):
+        logger.exception('Exception happened during processing of request '
+                         'from %s', client_address)
+
+
+def main(argv=sys.argv):
+    """Entry point for starting a TCP git server."""
+    if len(argv) > 1:
+        gitdir = argv[1]
+    else:
+        gitdir = '.'
+
+    log_utils.default_logging_config()
+    backend = DictBackend({'/': Repo(gitdir)})
+    server = TCPGitServer(backend, 'localhost')
+    server.serve_forever()
+
+
+def serve_command(handler_cls, argv=sys.argv, backend=None, inf=sys.stdin,
+                  outf=sys.stdout):
+    """Serve a single command.
+
+    This is mostly useful for the implementation of commands used by e.g. git+ssh.
+
+    :param handler_cls: `Handler` class to use for the request
+    :param argv: execv-style command-line arguments. Defaults to sys.argv.
+    :param backend: `Backend` to use
+    :param inf: File-like object to read from, defaults to standard input.
+    :param outf: File-like object to write to, defaults to standard output.
+    :return: Exit code for use with sys.exit. 0 on success, 1 on failure.
+    """
+    if backend is None:
+        backend = FileSystemBackend()
+    def send_fn(data):
+        outf.write(data)
+        outf.flush()
+    proto = Protocol(inf.read, send_fn)
+    handler = handler_cls(backend, argv[1:], proto)
+    # FIXME: Catch exceptions and write a single-line summary to outf.
+    handler.handle()
+    return 0

=== modified file 'dulwich/tests/__init__.py'
--- dulwich/tests/__init__.py	2009-05-19 19:09:14 +0000
+++ dulwich/tests/__init__.py	2011-01-05 11:30:29 +0000
@@ -1,20 +1,134 @@
 # __init__.py -- The tests for dulwich
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
-# 
+#
 # 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 
+# 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.
 
 """Tests for Dulwich."""
+
+import doctest
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+
+if sys.version_info >= (2, 7):
+    # If Python itself provides an exception, use that
+    import unittest
+    from unittest import SkipTest as TestSkipped
+    from unittest import TestCase
+else:
+    try:
+        import unittest2 as unittest
+        from unittest2 import SkipTest as TestSkipped
+        from unittest2 import TestCase
+    except ImportError:
+        import unittest
+        from testtools.testcase import TestSkipped
+        from testtools.testcase import TestCase
+        TestCase.skipException = TestSkipped
+
+
+class BlackboxTestCase(TestCase):
+    """Blackbox testing."""
+
+    bin_directory = os.path.abspath(os.path.join(os.path.dirname(__file__),
+        "..", "..", "bin"))
+
+    def bin_path(self, name):
+        """Determine the full path of a binary.
+
+        :param name: Name of the script
+        :return: Full path
+        """
+        return os.path.join(self.bin_directory, name)
+
+    def run_command(self, name, args):
+        """Run a Dulwich command.
+
+        :param name: Name of the command, as it exists in bin/
+        :param args: Arguments to the command
+        """
+        env = dict(os.environ)
+        env["PYTHONPATH"] = os.pathsep.join(sys.path)
+
+        # Since they don't have any extensions, Windows can't recognize
+        # executablility of the Python files in /bin. Even then, we'd have to
+        # expect the user to set up file associations for .py files.
+        #
+        # Save us from all that headache and call python with the bin script.
+        argv = [sys.executable, self.bin_path(name)] + args
+        return subprocess.Popen(argv,
+            stdout=subprocess.PIPE,
+            stdin=subprocess.PIPE, stderr=subprocess.PIPE,
+            env=env)
+
+
+def self_test_suite():
+    names = [
+        'blackbox',
+        'client',
+        'fastexport',
+        'file',
+        'index',
+        'lru_cache',
+        'objects',
+        'object_store',
+        'pack',
+        'patch',
+        'protocol',
+        'repository',
+        'server',
+        'web',
+        ]
+    module_names = ['dulwich.tests.test_' + name for name in names]
+    loader = unittest.TestLoader()
+    return loader.loadTestsFromNames(module_names)
+
+
+def tutorial_test_suite():
+    tutorial = [
+        '0-introduction',
+        '1-repo',
+        '2-object-store',
+        '3-conclusion',
+        ]
+    tutorial_files = ["../../docs/tutorial/%s.txt" % name for name in tutorial]
+    def setup(test):
+        test.__dulwich_tempdir = tempfile.mkdtemp()
+        os.chdir(test.__dulwich_tempdir)
+    def teardown(test):
+        shutil.rmtree(test.__dulwich_tempdir)
+    return doctest.DocFileSuite(setUp=setup, tearDown=teardown,
+        *tutorial_files)
+
+
+def nocompat_test_suite():
+    result = unittest.TestSuite()
+    result.addTests(self_test_suite())
+    result.addTests(tutorial_test_suite())
+    return result
+
+
+def test_suite():
+    result = unittest.TestSuite()
+    result.addTests(self_test_suite())
+    result.addTests(tutorial_test_suite())
+    from dulwich.tests.compat import test_suite as compat_test_suite
+    result.addTests(compat_test_suite())
+    return result

=== added directory 'dulwich/tests/compat'
=== added file 'dulwich/tests/compat/__init__.py'
--- dulwich/tests/compat/__init__.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/__init__.py	2010-12-19 18:27:27 +0000
@@ -0,0 +1,37 @@
+# __init__.py -- Compatibility tests for dulwich
+# Copyright (C) 2010 Jelmer Vernooij <jelmer@xxxxxxxxx>
+#
+# 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.
+
+"""Compatibility tests for Dulwich."""
+
+import unittest
+
+def test_suite():
+    names = [
+        'client',
+        'pack',
+        'repository',
+        'server',
+        'utils',
+        ]
+    module_names = ['dulwich.tests.compat.test_' + name for name in names]
+    result = unittest.TestSuite()
+    loader = unittest.TestLoader()
+    suite = loader.loadTestsFromNames(module_names)
+    result.addTests(suite)
+    return result

=== added file 'dulwich/tests/compat/server_utils.py'
--- dulwich/tests/compat/server_utils.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/server_utils.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,192 @@
+# server_utils.py -- Git server compatibility utilities
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Utilities for testing git server compatibility."""
+
+
+import select
+import socket
+import threading
+
+from dulwich.server import (
+    ReceivePackHandler,
+    )
+from dulwich.tests.utils import (
+    tear_down_repo,
+    )
+from dulwich.tests.compat.utils import (
+    import_repo,
+    run_git_or_fail,
+    )
+
+
+class ServerTests(object):
+    """Base tests for testing servers.
+
+    Does not inherit from TestCase so tests are not automatically run.
+    """
+
+    def setUp(self):
+        self._old_repo = None
+        self._new_repo = None
+        self._server = None
+
+    def tearDown(self):
+        if self._server is not None:
+            self._server.shutdown()
+            self._server = None
+        if self._old_repo is not None:
+            tear_down_repo(self._old_repo)
+        if self._new_repo is not None:
+            tear_down_repo(self._new_repo)
+
+    def import_repos(self):
+        self._old_repo = import_repo('server_old.export')
+        self._new_repo = import_repo('server_new.export')
+
+    def url(self, port):
+        return '%s://localhost:%s/' % (self.protocol, port)
+
+    def branch_args(self, branches=None):
+        if branches is None:
+            branches = ['master', 'branch']
+        return ['%s:%s' % (b, b) for b in branches]
+
+    def test_push_to_dulwich(self):
+        self.import_repos()
+        self.assertReposNotEqual(self._old_repo, self._new_repo)
+        port = self._start_server(self._old_repo)
+
+        run_git_or_fail(['push', self.url(port)] + self.branch_args(),
+                        cwd=self._new_repo.path)
+        self.assertReposEqual(self._old_repo, self._new_repo)
+
+    def test_fetch_from_dulwich(self):
+        self.import_repos()
+        self.assertReposNotEqual(self._old_repo, self._new_repo)
+        port = self._start_server(self._new_repo)
+
+        run_git_or_fail(['fetch', self.url(port)] + self.branch_args(),
+                        cwd=self._old_repo.path)
+        # flush the pack cache so any new packs are picked up
+        self._old_repo.object_store._pack_cache = None
+        self.assertReposEqual(self._old_repo, self._new_repo)
+
+    def test_fetch_from_dulwich_no_op(self):
+        self._old_repo = import_repo('server_old.export')
+        self._new_repo = import_repo('server_old.export')
+        self.assertReposEqual(self._old_repo, self._new_repo)
+        port = self._start_server(self._new_repo)
+
+        run_git_or_fail(['fetch', self.url(port)] + self.branch_args(),
+                        cwd=self._old_repo.path)
+        # flush the pack cache so any new packs are picked up
+        self._old_repo.object_store._pack_cache = None
+        self.assertReposEqual(self._old_repo, self._new_repo)
+
+
+class ShutdownServerMixIn:
+    """Mixin that allows serve_forever to be shut down.
+
+    The methods in this mixin are backported from SocketServer.py in the Python
+    2.6.4 standard library. The mixin is unnecessary in 2.6 and later, when
+    BaseServer supports the shutdown method directly.
+    """
+
+    def __init__(self):
+        self.__is_shut_down = threading.Event()
+        self.__serving = False
+
+    def serve_forever(self, poll_interval=0.5):
+        """Handle one request at a time until shutdown.
+
+        Polls for shutdown every poll_interval seconds. Ignores
+        self.timeout. If you need to do periodic tasks, do them in
+        another thread.
+        """
+        self.__serving = True
+        self.__is_shut_down.clear()
+        while self.__serving:
+            # XXX: Consider using another file descriptor or
+            # connecting to the socket to wake this up instead of
+            # polling. Polling reduces our responsiveness to a
+            # shutdown request and wastes cpu at all other times.
+            r, w, e = select.select([self], [], [], poll_interval)
+            if r:
+                self._handle_request_noblock()
+        self.__is_shut_down.set()
+
+    serve = serve_forever  # override alias from TCPGitServer
+
+    def shutdown(self):
+        """Stops the serve_forever loop.
+
+        Blocks until the loop has finished. This must be called while
+        serve_forever() is running in another thread, or it will deadlock.
+        """
+        self.__serving = False
+        self.__is_shut_down.wait()
+
+    def handle_request(self):
+        """Handle one request, possibly blocking.
+
+        Respects self.timeout.
+        """
+        # Support people who used socket.settimeout() to escape
+        # handle_request before self.timeout was available.
+        timeout = self.socket.gettimeout()
+        if timeout is None:
+            timeout = self.timeout
+        elif self.timeout is not None:
+            timeout = min(timeout, self.timeout)
+        fd_sets = select.select([self], [], [], timeout)
+        if not fd_sets[0]:
+            self.handle_timeout()
+            return
+        self._handle_request_noblock()
+
+    def _handle_request_noblock(self):
+        """Handle one request, without blocking.
+
+        I assume that select.select has returned that the socket is
+        readable before this function was called, so there should be
+        no risk of blocking in get_request().
+        """
+        try:
+            request, client_address = self.get_request()
+        except socket.error:
+            return
+        if self.verify_request(request, client_address):
+            try:
+                self.process_request(request, client_address)
+            except:
+                self.handle_error(request, client_address)
+                self.close_request(request)
+
+
+# TODO(dborowitz): Come up with a better way of testing various permutations of
+# capabilities. The only reason it is the way it is now is that side-band-64k
+# was only recently introduced into git-receive-pack.
+class NoSideBand64kReceivePackHandler(ReceivePackHandler):
+    """ReceivePackHandler that does not support side-band-64k."""
+
+    @classmethod
+    def capabilities(cls):
+        return tuple(c for c in ReceivePackHandler.capabilities()
+                     if c != 'side-band-64k')

=== added file 'dulwich/tests/compat/test_client.py'
--- dulwich/tests/compat/test_client.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/test_client.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,251 @@
+# test_client.py -- Compatibilty tests for git client.
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Compatibilty tests between the Dulwich client and the cgit server."""
+
+import os
+import shutil
+import signal
+import subprocess
+import tempfile
+
+from dulwich import (
+    client,
+    errors,
+    file,
+    index,
+    protocol,
+    objects,
+    repo,
+    )
+from dulwich.tests import (
+    TestSkipped,
+    )
+
+from dulwich.tests.compat.utils import (
+    CompatTestCase,
+    check_for_daemon,
+    import_repo_to_dir,
+    run_git_or_fail,
+    )
+
+
+class DulwichClientTestBase(object):
+    """Tests for client/server compatibility."""
+
+    def setUp(self):
+        self.gitroot = os.path.dirname(import_repo_to_dir('server_new.export'))
+        dest = os.path.join(self.gitroot, 'dest')
+        file.ensure_dir_exists(dest)
+        run_git_or_fail(['init', '--quiet', '--bare'], cwd=dest)
+
+    def tearDown(self):
+        shutil.rmtree(self.gitroot)
+
+    def assertDestEqualsSrc(self):
+        src = repo.Repo(os.path.join(self.gitroot, 'server_new.export'))
+        dest = repo.Repo(os.path.join(self.gitroot, 'dest'))
+        self.assertReposEqual(src, dest)
+
+    def _client(self):
+        raise NotImplementedError()
+
+    def _build_path(self):
+        raise NotImplementedError()
+
+    def _do_send_pack(self):
+        c = self._client()
+        srcpath = os.path.join(self.gitroot, 'server_new.export')
+        src = repo.Repo(srcpath)
+        sendrefs = dict(src.get_refs())
+        del sendrefs['HEAD']
+        c.send_pack(self._build_path('/dest'), lambda _: sendrefs,
+                    src.object_store.generate_pack_contents)
+
+    def test_send_pack(self):
+        self._do_send_pack()
+        self.assertDestEqualsSrc()
+
+    def test_send_pack_nothing_to_send(self):
+        self._do_send_pack()
+        self.assertDestEqualsSrc()
+        # nothing to send, but shouldn't raise either.
+        self._do_send_pack()
+
+    def test_send_without_report_status(self):
+        c = self._client()
+        c._send_capabilities.remove('report-status')
+        srcpath = os.path.join(self.gitroot, 'server_new.export')
+        src = repo.Repo(srcpath)
+        sendrefs = dict(src.get_refs())
+        del sendrefs['HEAD']
+        c.send_pack(self._build_path('/dest'), lambda _: sendrefs,
+                    src.object_store.generate_pack_contents)
+        self.assertDestEqualsSrc()
+
+    def disable_ff_and_make_dummy_commit(self):
+        # disable non-fast-forward pushes to the server
+        dest = repo.Repo(os.path.join(self.gitroot, 'dest'))
+        run_git_or_fail(['config', 'receive.denyNonFastForwards', 'true'],
+                        cwd=dest.path)
+        b = objects.Blob.from_string('hi')
+        dest.object_store.add_object(b)
+        t = index.commit_tree(dest.object_store, [('hi', b.id, 0100644)])
+        c = objects.Commit()
+        c.author = c.committer = 'Foo Bar <foo@xxxxxxxxxxx>'
+        c.author_time = c.commit_time = 0
+        c.author_timezone = c.commit_timezone = 0
+        c.message = 'hi'
+        c.tree = t
+        dest.object_store.add_object(c)
+        return dest, c.id
+
+    def compute_send(self):
+        srcpath = os.path.join(self.gitroot, 'server_new.export')
+        src = repo.Repo(srcpath)
+        sendrefs = dict(src.get_refs())
+        del sendrefs['HEAD']
+        return sendrefs, src.object_store.generate_pack_contents
+
+    def test_send_pack_one_error(self):
+        dest, dummy_commit = self.disable_ff_and_make_dummy_commit()
+        dest.refs['refs/heads/master'] = dummy_commit
+        sendrefs, gen_pack = self.compute_send()
+        c = self._client()
+        try:
+            c.send_pack(self._build_path('/dest'), lambda _: sendrefs, gen_pack)
+        except errors.UpdateRefsError, e:
+            self.assertEqual('refs/heads/master failed to update', str(e))
+            self.assertEqual({'refs/heads/branch': 'ok',
+                              'refs/heads/master': 'non-fast-forward'},
+                             e.ref_status)
+
+    def test_send_pack_multiple_errors(self):
+        dest, dummy = self.disable_ff_and_make_dummy_commit()
+        # set up for two non-ff errors
+        dest.refs['refs/heads/branch'] = dest.refs['refs/heads/master'] = dummy
+        sendrefs, gen_pack = self.compute_send()
+        c = self._client()
+        try:
+            c.send_pack(self._build_path('/dest'), lambda _: sendrefs, gen_pack)
+        except errors.UpdateRefsError, e:
+            self.assertEqual('refs/heads/branch, refs/heads/master failed to '
+                             'update', str(e))
+            self.assertEqual({'refs/heads/branch': 'non-fast-forward',
+                              'refs/heads/master': 'non-fast-forward'},
+                             e.ref_status)
+
+    def test_fetch_pack(self):
+        c = self._client()
+        dest = repo.Repo(os.path.join(self.gitroot, 'dest'))
+        refs = c.fetch(self._build_path('/server_new.export'), dest)
+        map(lambda r: dest.refs.set_if_equals(r[0], None, r[1]), refs.items())
+        self.assertDestEqualsSrc()
+
+    def test_incremental_fetch_pack(self):
+        self.test_fetch_pack()
+        dest, dummy = self.disable_ff_and_make_dummy_commit()
+        dest.refs['refs/heads/master'] = dummy
+        c = self._client()
+        dest = repo.Repo(os.path.join(self.gitroot, 'server_new.export'))
+        refs = c.fetch(self._build_path('/dest'), dest)
+        map(lambda r: dest.refs.set_if_equals(r[0], None, r[1]), refs.items())
+        self.assertDestEqualsSrc()
+
+
+class DulwichTCPClientTest(CompatTestCase, DulwichClientTestBase):
+
+    def setUp(self):
+        CompatTestCase.setUp(self)
+        DulwichClientTestBase.setUp(self)
+        if check_for_daemon(limit=1):
+            raise TestSkipped('git-daemon was already running on port %s' %
+                              protocol.TCP_GIT_PORT)
+        fd, self.pidfile = tempfile.mkstemp(prefix='dulwich-test-git-client',
+                                            suffix=".pid")
+        os.fdopen(fd).close()
+        run_git_or_fail(
+            ['daemon', '--verbose', '--export-all',
+             '--pid-file=%s' % self.pidfile, '--base-path=%s' % self.gitroot,
+             '--detach', '--reuseaddr', '--enable=receive-pack',
+             '--listen=localhost', self.gitroot], cwd=self.gitroot)
+        if not check_for_daemon():
+            raise TestSkipped('git-daemon failed to start')
+
+    def tearDown(self):
+        try:
+            os.kill(int(open(self.pidfile).read().strip()), signal.SIGKILL)
+            os.unlink(self.pidfile)
+        except (OSError, IOError):
+            pass
+        DulwichClientTestBase.tearDown(self)
+        CompatTestCase.tearDown(self)
+
+    def _client(self):
+        return client.TCPGitClient('localhost')
+
+    def _build_path(self, path):
+        return path
+
+
+class TestSSHVendor(object):
+    @staticmethod
+    def connect_ssh(host, command, username=None, port=None):
+        cmd, path = command[0].replace("'", '').split(' ')
+        cmd = cmd.split('-', 1)
+        p = subprocess.Popen(cmd + [path], stdin=subprocess.PIPE,
+                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        return client.SubprocessWrapper(p)
+
+
+class DulwichMockSSHClientTest(CompatTestCase, DulwichClientTestBase):
+
+    def setUp(self):
+        CompatTestCase.setUp(self)
+        DulwichClientTestBase.setUp(self)
+        self.real_vendor = client.get_ssh_vendor
+        client.get_ssh_vendor = TestSSHVendor
+
+    def tearDown(self):
+        DulwichClientTestBase.tearDown(self)
+        CompatTestCase.tearDown(self)
+        client.get_ssh_vendor = self.real_vendor
+
+    def _client(self):
+        return client.SSHGitClient('localhost')
+
+    def _build_path(self, path):
+        return self.gitroot + path
+
+
+class DulwichSubprocessClientTest(CompatTestCase, DulwichClientTestBase):
+
+    def setUp(self):
+        CompatTestCase.setUp(self)
+        DulwichClientTestBase.setUp(self)
+
+    def tearDown(self):
+        DulwichClientTestBase.tearDown(self)
+        CompatTestCase.tearDown(self)
+
+    def _client(self):
+        return client.SubprocessGitClient()
+
+    def _build_path(self, path):
+        return self.gitroot + path

=== added file 'dulwich/tests/compat/test_pack.py'
--- dulwich/tests/compat/test_pack.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/test_pack.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,70 @@
+# test_pack.py -- Compatibility tests for git packs.
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Compatibility tests for git packs."""
+
+
+import binascii
+import os
+import shutil
+import tempfile
+
+from dulwich.pack import (
+    write_pack,
+    )
+from dulwich.tests.test_pack import (
+    pack1_sha,
+    PackTests,
+    )
+from dulwich.tests.compat.utils import (
+    require_git_version,
+    run_git_or_fail,
+    )
+
+
+class TestPack(PackTests):
+    """Compatibility tests for reading and writing pack files."""
+
+    def setUp(self):
+        require_git_version((1, 5, 0))
+        PackTests.setUp(self)
+        self._tempdir = tempfile.mkdtemp()
+
+    def tearDown(self):
+        shutil.rmtree(self._tempdir)
+        PackTests.tearDown(self)
+
+    def test_copy(self):
+        origpack = self.get_pack(pack1_sha)
+        self.assertSucceeds(origpack.index.check)
+        pack_path = os.path.join(self._tempdir, "Elch")
+        write_pack(pack_path, [(x, "") for x in origpack.iterobjects()],
+                   len(origpack))
+        output = run_git_or_fail(['verify-pack', '-v', pack_path])
+
+        pack_shas = set()
+        for line in output.splitlines():
+            sha = line[:40]
+            try:
+                binascii.unhexlify(sha)
+            except TypeError:
+                continue  # non-sha line
+            pack_shas.add(sha)
+        orig_shas = set(o.id for o in origpack.iterobjects())
+        self.assertEquals(orig_shas, pack_shas)

=== added file 'dulwich/tests/compat/test_repository.py'
--- dulwich/tests/compat/test_repository.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/test_repository.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,128 @@
+# test_repo.py -- Git repo compatibility tests
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Compatibility tests for dulwich repositories."""
+
+
+from cStringIO import StringIO
+import itertools
+import os
+
+from dulwich.objects import (
+    hex_to_sha,
+    )
+from dulwich.repo import (
+    check_ref_format,
+    )
+from dulwich.tests.utils import (
+    tear_down_repo,
+    )
+
+from dulwich.tests.compat.utils import (
+    run_git_or_fail,
+    import_repo,
+    CompatTestCase,
+    )
+
+
+class ObjectStoreTestCase(CompatTestCase):
+    """Tests for git repository compatibility."""
+
+    def setUp(self):
+        CompatTestCase.setUp(self)
+        self._repo = import_repo('server_new.export')
+
+    def tearDown(self):
+        CompatTestCase.tearDown(self)
+        tear_down_repo(self._repo)
+
+    def _run_git(self, args):
+        return run_git_or_fail(args, cwd=self._repo.path)
+
+    def _parse_refs(self, output):
+        refs = {}
+        for line in StringIO(output):
+            fields = line.rstrip('\n').split(' ')
+            self.assertEqual(3, len(fields))
+            refname, type_name, sha = fields
+            check_ref_format(refname[5:])
+            hex_to_sha(sha)
+            refs[refname] = (type_name, sha)
+        return refs
+
+    def _parse_objects(self, output):
+        return set(s.rstrip('\n').split(' ')[0] for s in StringIO(output))
+
+    def test_bare(self):
+        self.assertTrue(self._repo.bare)
+        self.assertFalse(os.path.exists(os.path.join(self._repo.path, '.git')))
+
+    def test_head(self):
+        output = self._run_git(['rev-parse', 'HEAD'])
+        head_sha = output.rstrip('\n')
+        hex_to_sha(head_sha)
+        self.assertEqual(head_sha, self._repo.refs['HEAD'])
+
+    def test_refs(self):
+        output = self._run_git(
+          ['for-each-ref', '--format=%(refname) %(objecttype) %(objectname)'])
+        expected_refs = self._parse_refs(output)
+
+        actual_refs = {}
+        for refname, sha in self._repo.refs.as_dict().iteritems():
+            if refname == 'HEAD':
+                continue  # handled in test_head
+            obj = self._repo[sha]
+            self.assertEqual(sha, obj.id)
+            actual_refs[refname] = (obj.type_name, obj.id)
+        self.assertEqual(expected_refs, actual_refs)
+
+    # TODO(dborowitz): peeled ref tests
+
+    def _get_loose_shas(self):
+        output = self._run_git(['rev-list', '--all', '--objects', '--unpacked'])
+        return self._parse_objects(output)
+
+    def _get_all_shas(self):
+        output = self._run_git(['rev-list', '--all', '--objects'])
+        return self._parse_objects(output)
+
+    def assertShasMatch(self, expected_shas, actual_shas_iter):
+        actual_shas = set()
+        for sha in actual_shas_iter:
+            obj = self._repo[sha]
+            self.assertEqual(sha, obj.id)
+            actual_shas.add(sha)
+        self.assertEqual(expected_shas, actual_shas)
+
+    def test_loose_objects(self):
+        # TODO(dborowitz): This is currently not very useful since fast-imported
+        # repos only contained packed objects.
+        expected_shas = self._get_loose_shas()
+        self.assertShasMatch(expected_shas,
+                             self._repo.object_store._iter_loose_objects())
+
+    def test_packed_objects(self):
+        expected_shas = self._get_all_shas() - self._get_loose_shas()
+        self.assertShasMatch(expected_shas,
+                             itertools.chain(*self._repo.object_store.packs))
+
+    def test_all_objects(self):
+        expected_shas = self._get_all_shas()
+        self.assertShasMatch(expected_shas, iter(self._repo.object_store))

=== added file 'dulwich/tests/compat/test_server.py'
--- dulwich/tests/compat/test_server.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/test_server.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,104 @@
+# test_server.py -- Compatibility tests for git server.
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Compatibility tests between Dulwich and the cgit server.
+
+Warning: these tests should be fairly stable, but when writing/debugging new
+    tests, deadlocks may freeze the test process such that it cannot be
+    Ctrl-C'ed. On POSIX systems, you can kill the tests with Ctrl-Z, "kill %".
+"""
+
+import threading
+
+from dulwich.server import (
+    DictBackend,
+    TCPGitServer,
+    )
+from dulwich.tests.compat.server_utils import (
+    ServerTests,
+    ShutdownServerMixIn,
+    NoSideBand64kReceivePackHandler,
+    )
+from dulwich.tests.compat.utils import (
+    CompatTestCase,
+    )
+
+
+if not getattr(TCPGitServer, 'shutdown', None):
+    _TCPGitServer = TCPGitServer
+
+    class TCPGitServer(ShutdownServerMixIn, TCPGitServer):
+        """Subclass of TCPGitServer that can be shut down."""
+
+        def __init__(self, *args, **kwargs):
+            # BaseServer is old-style so we have to call both __init__s
+            ShutdownServerMixIn.__init__(self)
+            _TCPGitServer.__init__(self, *args, **kwargs)
+
+        serve = ShutdownServerMixIn.serve_forever
+
+
+class GitServerTestCase(ServerTests, CompatTestCase):
+    """Tests for client/server compatibility.
+
+    This server test case does not use side-band-64k in git-receive-pack.
+    """
+
+    protocol = 'git'
+
+    def setUp(self):
+        ServerTests.setUp(self)
+        CompatTestCase.setUp(self)
+
+    def tearDown(self):
+        ServerTests.tearDown(self)
+        CompatTestCase.tearDown(self)
+
+    def _handlers(self):
+        return {'git-receive-pack': NoSideBand64kReceivePackHandler}
+
+    def _check_server(self, dul_server):
+        receive_pack_handler_cls = dul_server.handlers['git-receive-pack']
+        caps = receive_pack_handler_cls.capabilities()
+        self.assertFalse('side-band-64k' in caps)
+
+    def _start_server(self, repo):
+        backend = DictBackend({'/': repo})
+        dul_server = TCPGitServer(backend, 'localhost', 0,
+                                  handlers=self._handlers())
+        self._check_server(dul_server)
+        threading.Thread(target=dul_server.serve).start()
+        self._server = dul_server
+        _, port = self._server.socket.getsockname()
+        return port
+
+
+class GitServerSideBand64kTestCase(GitServerTestCase):
+    """Tests for client/server compatibility with side-band-64k support."""
+
+    # side-band-64k in git-receive-pack was introduced in git 1.7.0.2
+    min_git_version = (1, 7, 0, 2)
+
+    def _handlers(self):
+        return None  # default handlers include side-band-64k
+
+    def _check_server(self, server):
+        receive_pack_handler_cls = server.handlers['git-receive-pack']
+        caps = receive_pack_handler_cls.capabilities()
+        self.assertTrue('side-band-64k' in caps)

=== added file 'dulwich/tests/compat/test_utils.py'
--- dulwich/tests/compat/test_utils.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/test_utils.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,92 @@
+# test_utils.py -- Tests for git compatibility utilities
+# Copyright (C) 2010 Google, Inc.
+#
+# 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; either version 2
+# of the License, or (at your option) any later version.
+#
+# 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.
+
+"""Tests for git compatibility utilities."""
+
+from dulwich.tests import (
+    TestCase,
+    TestSkipped,
+    )
+from dulwich.tests.compat import utils
+
+
+class GitVersionTests(TestCase):
+
+    def setUp(self):
+        super(GitVersionTests, self).setUp()
+        self._orig_run_git = utils.run_git
+        self._version_str = None  # tests can override to set stub version
+
+        def run_git(args, **unused_kwargs):
+            self.assertEqual(['--version'], args)
+            return 0, self._version_str
+        utils.run_git = run_git
+
+    def tearDown(self):
+        super(GitVersionTests, self).tearDown()
+        utils.run_git = self._orig_run_git
+
+    def test_git_version_none(self):
+        self._version_str = 'not a git version'
+        self.assertEqual(None, utils.git_version())
+
+    def test_git_version_3(self):
+        self._version_str = 'git version 1.6.6'
+        self.assertEqual((1, 6, 6, 0), utils.git_version())
+
+    def test_git_version_4(self):
+        self._version_str = 'git version 1.7.0.2'
+        self.assertEqual((1, 7, 0, 2), utils.git_version())
+
+    def test_git_version_extra(self):
+        self._version_str = 'git version 1.7.0.3.295.gd8fa2'
+        self.assertEqual((1, 7, 0, 3), utils.git_version())
+
+    def assertRequireSucceeds(self, required_version):
+        try:
+            utils.require_git_version(required_version)
+        except TestSkipped:
+            self.fail()
+
+    def assertRequireFails(self, required_version):
+        self.assertRaises(TestSkipped, utils.require_git_version,
+                          required_version)
+
+    def test_require_git_version(self):
+        try:
+            self._version_str = 'git version 1.6.6'
+            self.assertRequireSucceeds((1, 6, 6))
+            self.assertRequireSucceeds((1, 6, 6, 0))
+            self.assertRequireSucceeds((1, 6, 5))
+            self.assertRequireSucceeds((1, 6, 5, 99))
+            self.assertRequireFails((1, 7, 0))
+            self.assertRequireFails((1, 7, 0, 2))
+            self.assertRaises(ValueError, utils.require_git_version,
+                              (1, 6, 6, 0, 0))
+
+            self._version_str = 'git version 1.7.0.2'
+            self.assertRequireSucceeds((1, 6, 6))
+            self.assertRequireSucceeds((1, 6, 6, 0))
+            self.assertRequireSucceeds((1, 7, 0))
+            self.assertRequireSucceeds((1, 7, 0, 2))
+            self.assertRequireFails((1, 7, 0, 3))
+            self.assertRequireFails((1, 7, 1))
+        except TestSkipped, e:
+            # This test is designed to catch all TestSkipped exceptions.
+            self.fail('Test unexpectedly skipped: %s' % e)

=== added file 'dulwich/tests/compat/test_web.py'
--- dulwich/tests/compat/test_web.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/test_web.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,147 @@
+# test_web.py -- Compatibility tests for the git web server.
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Compatibility tests between Dulwich and the cgit HTTP server.
+
+warning: these tests should be fairly stable, but when writing/debugging new
+    tests, deadlocks may freeze the test process such that it cannot be
+    Ctrl-C'ed. On POSIX systems, you can kill the tests with Ctrl-Z, "kill %".
+"""
+
+import threading
+from wsgiref import simple_server
+
+from dulwich.server import (
+    DictBackend,
+    )
+from dulwich.tests import (
+    TestSkipped,
+    )
+from dulwich.web import (
+    HTTPGitApplication,
+    HTTPGitRequestHandler,
+    )
+
+from dulwich.tests.compat.server_utils import (
+    ServerTests,
+    ShutdownServerMixIn,
+    NoSideBand64kReceivePackHandler,
+    )
+from dulwich.utils import (
+    CompatTestCase,
+    )
+
+
+if getattr(simple_server.WSGIServer, 'shutdown', None):
+    WSGIServer = simple_server.WSGIServer
+else:
+    class WSGIServer(ShutdownServerMixIn, simple_server.WSGIServer):
+        """Subclass of WSGIServer that can be shut down."""
+
+        def __init__(self, *args, **kwargs):
+            # BaseServer is old-style so we have to call both __init__s
+            ShutdownServerMixIn.__init__(self)
+            simple_server.WSGIServer.__init__(self, *args, **kwargs)
+
+        serve = ShutdownServerMixIn.serve_forever
+
+
+class WebTests(ServerTests):
+    """Base tests for web server tests.
+
+    Contains utility and setUp/tearDown methods, but does non inherit from
+    TestCase so tests are not automatically run.
+    """
+
+    protocol = 'http'
+
+    def _start_server(self, repo):
+        backend = DictBackend({'/': repo})
+        app = self._make_app(backend)
+        dul_server = simple_server.make_server(
+          'localhost', 0, app, server_class=WSGIServer,
+          handler_class=HTTPGitRequestHandler)
+        threading.Thread(target=dul_server.serve_forever).start()
+        self._server = dul_server
+        _, port = dul_server.socket.getsockname()
+        return port
+
+
+class SmartWebTestCase(WebTests, CompatTestCase):
+    """Test cases for smart HTTP server.
+
+    This server test case does not use side-band-64k in git-receive-pack.
+    """
+
+    min_git_version = (1, 6, 6)
+
+    def setUp(self):
+        WebTests.setUp(self)
+        CompatTestCase.setUp(self)
+
+    def tearDown(self):
+        WebTests.tearDown(self)
+        CompatTestCase.tearDown(self)
+
+    def _handlers(self):
+        return {'git-receive-pack': NoSideBand64kReceivePackHandler}
+
+    def _check_app(self, app):
+        receive_pack_handler_cls = app.handlers['git-receive-pack']
+        caps = receive_pack_handler_cls.capabilities()
+        self.assertFalse('side-band-64k' in caps)
+
+    def _make_app(self, backend):
+        app = HTTPGitApplication(backend, handlers=self._handlers())
+        self._check_app(app)
+        return app
+
+
+class SmartWebSideBand64kTestCase(SmartWebTestCase):
+    """Test cases for smart HTTP server with side-band-64k support."""
+
+    # side-band-64k in git-receive-pack was introduced in git 1.7.0.2
+    min_git_version = (1, 7, 0, 2)
+
+    def _handlers(self):
+        return None  # default handlers include side-band-64k
+
+    def _check_app(self, app):
+        receive_pack_handler_cls = app.handlers['git-receive-pack']
+        caps = receive_pack_handler_cls.capabilities()
+        self.assertTrue('side-band-64k' in caps)
+
+
+class DumbWebTestCase(WebTests, CompatTestCase):
+    """Test cases for dumb HTTP server."""
+
+    def setUp(self):
+        WebTests.setUp(self)
+        CompatTestCase.setUp(self)
+
+    def tearDown(self):
+        WebTests.tearDown(self)
+        CompatTestCase.tearDown(self)
+
+    def _make_app(self, backend):
+        return HTTPGitApplication(backend, dumb=True)
+
+    def test_push_to_dulwich(self):
+        # Note: remove this if dumb pushing is supported
+        raise TestSkipped('Dumb web pushing not supported.')

=== added file 'dulwich/tests/compat/utils.py'
--- dulwich/tests/compat/utils.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/compat/utils.py	2010-12-19 18:56:40 +0000
@@ -0,0 +1,222 @@
+# utils.py -- Git compatibility utilities
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Utilities for interacting with cgit."""
+
+import errno
+import os
+import socket
+import subprocess
+import tempfile
+import time
+
+from dulwich.repo import Repo
+from dulwich.protocol import TCP_GIT_PORT
+
+from dulwich.tests import (
+    TestCase,
+    TestSkipped,
+    )
+
+_DEFAULT_GIT = 'git'
+_VERSION_LEN = 4
+_REPOS_DATA_DIR = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), os.pardir, 'data', 'repos'))
+
+
+def git_version(git_path=_DEFAULT_GIT):
+    """Attempt to determine the version of git currently installed.
+
+    :param git_path: Path to the git executable; defaults to the version in
+        the system path.
+    :return: A tuple of ints of the form (major, minor, point, sub-point), or
+        None if no git installation was found.
+    """
+    try:
+        output = run_git_or_fail(['--version'], git_path=git_path)
+    except OSError:
+        return None
+    version_prefix = 'git version '
+    if not output.startswith(version_prefix):
+        return None
+
+    parts = output[len(version_prefix):].split('.')
+    nums = []
+    for part in parts:
+        try:
+            nums.append(int(part))
+        except ValueError:
+            break
+
+    while len(nums) < _VERSION_LEN:
+        nums.append(0)
+    return tuple(nums[:_VERSION_LEN])
+
+
+def require_git_version(required_version, git_path=_DEFAULT_GIT):
+    """Require git version >= version, or skip the calling test.
+
+    :param required_version: A tuple of ints of the form (major, minor, point,
+        sub-point); ommitted components default to 0.
+    :param git_path: Path to the git executable; defaults to the version in
+        the system path.
+    :raise ValueError: if the required version tuple has too many parts.
+    :raise TestSkipped: if no suitable git version was found at the given path.
+    """
+    found_version = git_version(git_path=git_path)
+    if found_version is None:
+        raise TestSkipped('Test requires git >= %s, but c git not found' %
+                         (required_version, ))
+
+    if len(required_version) > _VERSION_LEN:
+        raise ValueError('Invalid version tuple %s, expected %i parts' %
+                         (required_version, _VERSION_LEN))
+
+    required_version = list(required_version)
+    while len(found_version) < len(required_version):
+        required_version.append(0)
+    required_version = tuple(required_version)
+
+    if found_version < required_version:
+        required_version = '.'.join(map(str, required_version))
+        found_version = '.'.join(map(str, found_version))
+        raise TestSkipped('Test requires git >= %s, found %s' %
+                         (required_version, found_version))
+
+
+def run_git(args, git_path=_DEFAULT_GIT, input=None, capture_stdout=False,
+            **popen_kwargs):
+    """Run a git command.
+
+    Input is piped from the input parameter and output is sent to the standard
+    streams, unless capture_stdout is set.
+
+    :param args: A list of args to the git command.
+    :param git_path: Path to to the git executable.
+    :param input: Input data to be sent to stdin.
+    :param capture_stdout: Whether to capture and return stdout.
+    :param popen_kwargs: Additional kwargs for subprocess.Popen;
+        stdin/stdout args are ignored.
+    :return: A tuple of (returncode, stdout contents). If capture_stdout is
+        False, None will be returned as stdout contents.
+    :raise OSError: if the git executable was not found.
+    """
+    args = [git_path] + args
+    popen_kwargs['stdin'] = subprocess.PIPE
+    if capture_stdout:
+        popen_kwargs['stdout'] = subprocess.PIPE
+    else:
+        popen_kwargs.pop('stdout', None)
+    p = subprocess.Popen(args, **popen_kwargs)
+    stdout, stderr = p.communicate(input=input)
+    return (p.returncode, stdout)
+
+
+def run_git_or_fail(args, git_path=_DEFAULT_GIT, input=None, **popen_kwargs):
+    """Run a git command, capture stdout/stderr, and fail if git fails."""
+    popen_kwargs['stderr'] = subprocess.STDOUT
+    returncode, stdout = run_git(args, git_path=git_path, input=input,
+                                 capture_stdout=True, **popen_kwargs)
+    assert returncode == 0
+    return stdout
+
+
+def import_repo_to_dir(name):
+    """Import a repo from a fast-export file in a temporary directory.
+
+    These are used rather than binary repos for compat tests because they are
+    more compact an human-editable, and we already depend on git.
+
+    :param name: The name of the repository export file, relative to
+        dulwich/tests/data/repos.
+    :returns: The path to the imported repository.
+    """
+    temp_dir = tempfile.mkdtemp()
+    export_path = os.path.join(_REPOS_DATA_DIR, name)
+    temp_repo_dir = os.path.join(temp_dir, name)
+    export_file = open(export_path, 'rb')
+    run_git_or_fail(['init', '--quiet', '--bare', temp_repo_dir])
+    run_git_or_fail(['fast-import'], input=export_file.read(),
+                    cwd=temp_repo_dir)
+    export_file.close()
+    return temp_repo_dir
+
+
+def import_repo(name):
+    """Import a repo from a fast-export file in a temporary directory.
+
+    :param name: The name of the repository export file, relative to
+        dulwich/tests/data/repos.
+    :returns: An initialized Repo object that lives in a temporary directory.
+    """
+    return Repo(import_repo_to_dir(name))
+
+
+def check_for_daemon(limit=10, delay=0.1, timeout=0.1, port=TCP_GIT_PORT):
+    """Check for a running TCP daemon.
+
+    Defaults to checking 10 times with a delay of 0.1 sec between tries.
+
+    :param limit: Number of attempts before deciding no daemon is running.
+    :param delay: Delay between connection attempts.
+    :param timeout: Socket timeout for connection attempts.
+    :param port: Port on which we expect the daemon to appear.
+    :returns: A boolean, true if a daemon is running on the specified port,
+        false if not.
+    """
+    for _ in xrange(limit):
+        time.sleep(delay)
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.settimeout(delay)
+        try:
+            s.connect(('localhost', port))
+            s.close()
+            return True
+        except socket.error, e:
+            if getattr(e, 'errno', False) and e.errno != errno.ECONNREFUSED:
+                raise
+            elif e.args[0] != errno.ECONNREFUSED:
+                raise
+    return False
+
+
+class CompatTestCase(TestCase):
+    """Test case that requires git for compatibility checks.
+
+    Subclasses can change the git version required by overriding
+    min_git_version.
+    """
+
+    min_git_version = (1, 5, 0)
+
+    def setUp(self):
+        super(CompatTestCase, self).setUp()
+        require_git_version(self.min_git_version)
+
+    def assertReposEqual(self, repo1, repo2):
+        self.assertEqual(repo1.get_refs(), repo2.get_refs())
+        self.assertEqual(sorted(set(repo1.object_store)),
+                         sorted(set(repo2.object_store)))
+
+    def assertReposNotEqual(self, repo1, repo2):
+        refs1 = repo1.get_refs()
+        objs1 = set(repo1.object_store)
+        refs2 = repo2.get_refs()
+        objs2 = set(repo2.object_store)
+        self.assertFalse(refs1 == refs2 and objs1 == objs2)

=== added directory 'dulwich/tests/data/blobs/11'
=== added file 'dulwich/tests/data/blobs/11/11111111111111111111111111111111111111'
Binary files dulwich/tests/data/blobs/11/11111111111111111111111111111111111111	1970-01-01 00:00:00 +0000 and dulwich/tests/data/blobs/11/11111111111111111111111111111111111111	2010-04-14 23:43:17 +0000 differ
=== added directory 'dulwich/tests/data/blobs/6f'
=== added file 'dulwich/tests/data/blobs/6f/670c0fb53f9463760b7295fbb814e965fb20c8'
Binary files dulwich/tests/data/blobs/6f/670c0fb53f9463760b7295fbb814e965fb20c8	1970-01-01 00:00:00 +0000 and dulwich/tests/data/blobs/6f/670c0fb53f9463760b7295fbb814e965fb20c8	2010-04-12 15:07:31 +0000 differ
=== removed file 'dulwich/tests/data/blobs/6f670c0fb53f9463760b7295fbb814e965fb20c8'
Binary files dulwich/tests/data/blobs/6f670c0fb53f9463760b7295fbb814e965fb20c8	2008-12-08 22:22:54 +0000 and dulwich/tests/data/blobs/6f670c0fb53f9463760b7295fbb814e965fb20c8	1970-01-01 00:00:00 +0000 differ
=== added directory 'dulwich/tests/data/blobs/95'
=== added file 'dulwich/tests/data/blobs/95/4a536f7819d40e6f637f849ee187dd10066349'
Binary files dulwich/tests/data/blobs/95/4a536f7819d40e6f637f849ee187dd10066349	1970-01-01 00:00:00 +0000 and dulwich/tests/data/blobs/95/4a536f7819d40e6f637f849ee187dd10066349	2010-04-12 15:07:31 +0000 differ
=== removed file 'dulwich/tests/data/blobs/954a536f7819d40e6f637f849ee187dd10066349'
Binary files dulwich/tests/data/blobs/954a536f7819d40e6f637f849ee187dd10066349	2008-12-08 22:22:54 +0000 and dulwich/tests/data/blobs/954a536f7819d40e6f637f849ee187dd10066349	1970-01-01 00:00:00 +0000 differ
=== added directory 'dulwich/tests/data/blobs/e6'
=== added file 'dulwich/tests/data/blobs/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391'
Binary files dulwich/tests/data/blobs/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391	1970-01-01 00:00:00 +0000 and dulwich/tests/data/blobs/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391	2010-04-12 15:07:31 +0000 differ
=== removed file 'dulwich/tests/data/blobs/e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'
Binary files dulwich/tests/data/blobs/e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	2008-12-08 22:22:54 +0000 and dulwich/tests/data/blobs/e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	1970-01-01 00:00:00 +0000 differ
=== added directory 'dulwich/tests/data/commits/0d'
=== added file 'dulwich/tests/data/commits/0d/89f20333fbb1d2f3a94da77f4981373d8f4310'
--- dulwich/tests/data/commits/0d/89f20333fbb1d2f3a94da77f4981373d8f4310	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/commits/0d/89f20333fbb1d2f3a94da77f4981373d8f4310	2010-04-12 15:07:31 +0000
@@ -0,0 +1,2 @@
+x���K
+�]�z��׮�=-&�����=��:�����=��)�����r�芔��>��4�wY���M��x��q=�s)&�Dh�{Y��m/�?�
\ No newline at end of file

=== removed file 'dulwich/tests/data/commits/0d89f20333fbb1d2f3a94da77f4981373d8f4310'
--- dulwich/tests/data/commits/0d89f20333fbb1d2f3a94da77f4981373d8f4310	2008-12-08 22:22:54 +0000
+++ dulwich/tests/data/commits/0d89f20333fbb1d2f3a94da77f4981373d8f4310	1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-x���K
-�]�z��׮�=-&�����=��:�����=��)�����r�芔��>��4�wY���M��x��q=�s)&�Dh�{Y��m/�?�
\ No newline at end of file

=== added directory 'dulwich/tests/data/commits/5d'
=== added file 'dulwich/tests/data/commits/5d/ac377bdded4c9aeb8dff595f0faeebcc8498cc'
Binary files dulwich/tests/data/commits/5d/ac377bdded4c9aeb8dff595f0faeebcc8498cc	1970-01-01 00:00:00 +0000 and dulwich/tests/data/commits/5d/ac377bdded4c9aeb8dff595f0faeebcc8498cc	2010-04-12 15:07:31 +0000 differ
=== removed file 'dulwich/tests/data/commits/5dac377bdded4c9aeb8dff595f0faeebcc8498cc'
Binary files dulwich/tests/data/commits/5dac377bdded4c9aeb8dff595f0faeebcc8498cc	2008-12-08 22:22:54 +0000 and dulwich/tests/data/commits/5dac377bdded4c9aeb8dff595f0faeebcc8498cc	1970-01-01 00:00:00 +0000 differ
=== added directory 'dulwich/tests/data/commits/60'
=== added file 'dulwich/tests/data/commits/60/dacdc733de308bb77bb76ce0fb0f9b44c9769e'
--- dulwich/tests/data/commits/60/dacdc733de308bb77bb76ce0fb0f9b44c9769e	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/commits/60/dacdc733de308bb77bb76ce0fb0f9b44c9769e	2010-04-12 15:07:31 +0000
@@ -0,0 +1,2 @@
+x����+�E]�/��"�]�g�	��5"���O���i�����a�	UB�E��r�[��P�\�����z靖-�zN�0Q
)ZO���E�v�,p�p��'l���<�|�k)P��GX�K����y�MQ
\ No newline at end of file

=== removed file 'dulwich/tests/data/commits/60dacdc733de308bb77bb76ce0fb0f9b44c9769e'
--- dulwich/tests/data/commits/60dacdc733de308bb77bb76ce0fb0f9b44c9769e	2008-12-08 22:22:54 +0000
+++ dulwich/tests/data/commits/60dacdc733de308bb77bb76ce0fb0f9b44c9769e	1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-x����-�E]�/��"�]�g�	��5"���O���i�����a�	UB�E��r�[��P�\�����z靖-�zN�0Q
)ZO���E�v�,p�p��'l���<�|�k)P��GX�K����y�MQ
\ No newline at end of file

=== added directory 'dulwich/tests/data/repos/a.git/objects/28'
=== added file 'dulwich/tests/data/repos/a.git/objects/28/237f4dc30d0d462658d6b937b08a0f0b6ef55a'
--- dulwich/tests/data/repos/a.git/objects/28/237f4dc30d0d462658d6b937b08a0f0b6ef55a	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/a.git/objects/28/237f4dc30d0d462658d6b937b08a0f0b6ef55a	2010-03-04 17:50:05 +0000
@@ -0,0 +1,2 @@
+x5�
+��a��@��i��""�L�T"uP�A7�o���2(0�H�\uB\]��N�c+���!0�5Zi-�)�~	��~�Ï��s��G�l���`�јk���0�
\ No newline at end of file

=== added directory 'dulwich/tests/data/repos/a.git/objects/b0'
=== added file 'dulwich/tests/data/repos/a.git/objects/b0/931cadc54336e78a1d980420e3268903b57a50'
--- dulwich/tests/data/repos/a.git/objects/b0/931cadc54336e78a1d980420e3268903b57a50	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/a.git/objects/b0/931cadc54336e78a1d980420e3268903b57a50	2010-03-04 17:50:05 +0000
@@ -0,0 +1,3 @@
+x-�[
+��I����7��T[o��RWo���
+�w��e�����7s��p��ی�h���kL[c7��������<�2�� �1Jr��������֥2v
\ No newline at end of file

=== added file 'dulwich/tests/data/repos/a.git/packed-refs'
--- dulwich/tests/data/repos/a.git/packed-refs	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/a.git/packed-refs	2010-03-04 17:50:05 +0000
@@ -0,0 +1,3 @@
+# pack-refs with: peeled 
+b0931cadc54336e78a1d980420e3268903b57a50 refs/tags/mytag-packed
+^2a72d929692c41d8554c07f6301757ba18a65d91

=== added directory 'dulwich/tests/data/repos/a.git/refs/tags'
=== added file 'dulwich/tests/data/repos/a.git/refs/tags/mytag'
--- dulwich/tests/data/repos/a.git/refs/tags/mytag	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/a.git/refs/tags/mytag	2010-03-04 17:50:05 +0000
@@ -0,0 +1,1 @@
+28237f4dc30d0d462658d6b937b08a0f0b6ef55a

=== added directory 'dulwich/tests/data/repos/refs.git'
=== added file 'dulwich/tests/data/repos/refs.git/HEAD'
--- dulwich/tests/data/repos/refs.git/HEAD	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/refs.git/HEAD	2010-02-09 17:51:20 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master

=== added directory 'dulwich/tests/data/repos/refs.git/objects'
=== added directory 'dulwich/tests/data/repos/refs.git/objects/3b'
=== added file 'dulwich/tests/data/repos/refs.git/objects/3b/9e5457140e738c2dcd39bf6d7acf88379b90d1'
Binary files dulwich/tests/data/repos/refs.git/objects/3b/9e5457140e738c2dcd39bf6d7acf88379b90d1	1970-01-01 00:00:00 +0000 and dulwich/tests/data/repos/refs.git/objects/3b/9e5457140e738c2dcd39bf6d7acf88379b90d1	2010-02-09 17:51:20 +0000 differ
=== added directory 'dulwich/tests/data/repos/refs.git/objects/3e'
=== added file 'dulwich/tests/data/repos/refs.git/objects/3e/c9c43c84ff242e3ef4a9fc5bc111fd780a76a8'
--- dulwich/tests/data/repos/refs.git/objects/3e/c9c43c84ff242e3ef4a9fc5bc111fd780a76a8	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/refs.git/objects/3e/c9c43c84ff242e3ef4a9fc5bc111fd780a76a8	2010-03-04 17:50:05 +0000
@@ -0,0 +1,3 @@
+x-�Q
+�D��m�V�i6���.���~��#Cm�]rwy����=�u�5^[�o��H<*y?ƴ,�()�����߈�����8x�R��.�Yk�t�Pa��Ե�
+q?��W)'���ǧ6
\ No newline at end of file

=== added directory 'dulwich/tests/data/repos/refs.git/objects/42'
=== added file 'dulwich/tests/data/repos/refs.git/objects/42/d06bd4b77fed026b154d16493e5deab78f02ec'
Binary files dulwich/tests/data/repos/refs.git/objects/42/d06bd4b77fed026b154d16493e5deab78f02ec	1970-01-01 00:00:00 +0000 and dulwich/tests/data/repos/refs.git/objects/42/d06bd4b77fed026b154d16493e5deab78f02ec	2010-02-09 17:51:20 +0000 differ
=== added directory 'dulwich/tests/data/repos/refs.git/objects/a1'
=== added file 'dulwich/tests/data/repos/refs.git/objects/a1/8114c31713746a33a2e70d9914d1ef3e781425'
Binary files dulwich/tests/data/repos/refs.git/objects/a1/8114c31713746a33a2e70d9914d1ef3e781425	1970-01-01 00:00:00 +0000 and dulwich/tests/data/repos/refs.git/objects/a1/8114c31713746a33a2e70d9914d1ef3e781425	2010-02-09 17:51:20 +0000 differ
=== added directory 'dulwich/tests/data/repos/refs.git/objects/cd'
=== added file 'dulwich/tests/data/repos/refs.git/objects/cd/a609072918d7b70057b6bef9f4c2537843fcfe'
--- dulwich/tests/data/repos/refs.git/objects/cd/a609072918d7b70057b6bef9f4c2537843fcfe	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/refs.git/objects/cd/a609072918d7b70057b6bef9f4c2537843fcfe	2010-03-04 17:50:05 +0000
@@ -0,0 +1,5 @@
+x-�Q
+�D�7i�V�i6�bIEOo
+~�`�Av�;�Zy����<*�^Z�o�\�T4
+�<	��.�Lam
+����#e�/�s�=�����Y��Bc��Q�k�����\r?)Y9�\ No newline at end of file

=== added directory 'dulwich/tests/data/repos/refs.git/objects/df'
=== added file 'dulwich/tests/data/repos/refs.git/objects/df/6800012397fb85c56e7418dd4eb9405dee075c'
Binary files dulwich/tests/data/repos/refs.git/objects/df/6800012397fb85c56e7418dd4eb9405dee075c	1970-01-01 00:00:00 +0000 and dulwich/tests/data/repos/refs.git/objects/df/6800012397fb85c56e7418dd4eb9405dee075c	2010-02-09 17:51:20 +0000 differ
=== added file 'dulwich/tests/data/repos/refs.git/packed-refs'
--- dulwich/tests/data/repos/refs.git/packed-refs	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/refs.git/packed-refs	2010-03-04 17:50:05 +0000
@@ -0,0 +1,4 @@
+# pack-refs with: peeled 
+df6800012397fb85c56e7418dd4eb9405dee075c refs/tags/refs-0.1
+^42d06bd4b77fed026b154d16493e5deab78f02ec
+42d06bd4b77fed026b154d16493e5deab78f02ec refs/heads/packed

=== added directory 'dulwich/tests/data/repos/refs.git/refs'
=== added directory 'dulwich/tests/data/repos/refs.git/refs/heads'
=== added file 'dulwich/tests/data/repos/refs.git/refs/heads/loop'
--- dulwich/tests/data/repos/refs.git/refs/heads/loop	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/refs.git/refs/heads/loop	2010-02-09 17:51:20 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/loop

=== added file 'dulwich/tests/data/repos/refs.git/refs/heads/master'
--- dulwich/tests/data/repos/refs.git/refs/heads/master	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/refs.git/refs/heads/master	2010-02-09 17:51:20 +0000
@@ -0,0 +1,1 @@
+42d06bd4b77fed026b154d16493e5deab78f02ec

=== added directory 'dulwich/tests/data/repos/refs.git/refs/tags'
=== added file 'dulwich/tests/data/repos/refs.git/refs/tags/refs-0.2'
--- dulwich/tests/data/repos/refs.git/refs/tags/refs-0.2	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/refs.git/refs/tags/refs-0.2	2010-03-04 17:50:05 +0000
@@ -0,0 +1,1 @@
+3ec9c43c84ff242e3ef4a9fc5bc111fd780a76a8

=== added file 'dulwich/tests/data/repos/server_new.export'
--- dulwich/tests/data/repos/server_new.export	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/server_new.export	2010-03-04 17:50:05 +0000
@@ -0,0 +1,99 @@
+blob
+mark :1
+data 13
+foo contents
+
+reset refs/heads/master
+commit refs/heads/master
+mark :2
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755064 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755064 -0800
+data 16
+initial checkin
+M 100644 :1 foo
+
+blob
+mark :3
+data 13
+baz contents
+
+blob
+mark :4
+data 21
+updated foo contents
+
+commit refs/heads/master
+mark :5
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755140 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755140 -0800
+data 15
+master checkin
+from :2
+M 100644 :3 baz
+M 100644 :4 foo
+
+blob
+mark :6
+data 24
+updated foo contents v2
+
+commit refs/heads/master
+mark :7
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755287 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755287 -0800
+data 17
+master checkin 2
+from :5
+M 100644 :6 foo
+
+blob
+mark :8
+data 24
+updated foo contents v3
+
+commit refs/heads/master
+mark :9
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755295 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755295 -0800
+data 17
+master checkin 3
+from :7
+M 100644 :8 foo
+
+blob
+mark :10
+data 22
+branched bar contents
+
+blob
+mark :11
+data 22
+branched foo contents
+
+commit refs/heads/branch
+mark :12
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755111 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755111 -0800
+data 15
+branch checkin
+from :2
+M 100644 :10 bar
+M 100644 :11 foo
+
+blob
+mark :13
+data 25
+branched bar contents v2
+
+commit refs/heads/branch
+mark :14
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755319 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755319 -0800
+data 17
+branch checkin 2
+from :12
+M 100644 :13 bar
+
+reset refs/heads/master
+from :9
+

=== added file 'dulwich/tests/data/repos/server_old.export'
--- dulwich/tests/data/repos/server_old.export	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/repos/server_old.export	2010-03-04 17:50:05 +0000
@@ -0,0 +1,57 @@
+blob
+mark :1
+data 13
+foo contents
+
+reset refs/heads/master
+commit refs/heads/master
+mark :2
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755064 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755064 -0800
+data 16
+initial checkin
+M 100644 :1 foo
+
+blob
+mark :3
+data 22
+branched bar contents
+
+blob
+mark :4
+data 22
+branched foo contents
+
+commit refs/heads/branch
+mark :5
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755111 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755111 -0800
+data 15
+branch checkin
+from :2
+M 100644 :3 bar
+M 100644 :4 foo
+
+blob
+mark :6
+data 13
+baz contents
+
+blob
+mark :7
+data 21
+updated foo contents
+
+commit refs/heads/master
+mark :8
+author Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755140 -0800
+committer Dave Borowitz <dborowitz@xxxxxxxxxx> 1265755140 -0800
+data 15
+master checkin
+from :2
+M 100644 :6 baz
+M 100644 :7 foo
+
+reset refs/heads/master
+from :8
+

=== added directory 'dulwich/tests/data/tags/71'
=== added file 'dulwich/tests/data/tags/71/033db03a03c6a36721efcf1968dd8f8e0cf023'
--- dulwich/tests/data/tags/71/033db03a03c6a36721efcf1968dd8f8e0cf023	1970-01-01 00:00:00 +0000
+++ dulwich/tests/data/tags/71/033db03a03c6a36721efcf1968dd8f8e0cf023	2010-04-12 15:07:31 +0000
@@ -0,0 +1,4 @@
+xm�MO�@�=��#݅��Q�IME����Q
+mʿ��G's�L2O�Sz���1�v��qnaJb+��0u3�mMr�
+a�����d���s,�=�RB bY(�֝�	Yj��n�p�	��7����#	ݜ5��!X�[��Gپ�M}n}�m�9p�d%�
+!��|��`��������%'�������C��5\��<a5E�Dp�D��=n�
�oKk��n~�6iM
\ No newline at end of file

=== removed file 'dulwich/tests/data/tags/71033db03a03c6a36721efcf1968dd8f8e0cf023'
--- dulwich/tests/data/tags/71033db03a03c6a36721efcf1968dd8f8e0cf023	2009-01-06 09:14:09 +0000
+++ dulwich/tests/data/tags/71033db03a03c6a36721efcf1968dd8f8e0cf023	1970-01-01 00:00:00 +0000
@@ -1,4 +0,0 @@
-xm�MO�@�=��#݅��Q�IME����Q
-mʿ��G's�L2O�Sz���1�v��qnaJb+��0u3�mMr�
-a�����d���s,�=�RB bY(�֝�	Yj��n�p�	��7����#	ݜ5��!X�[��Gپ�M}n}�m�9p�d%�
-!��|��`��������%'�������C��5\��<a5E�Dp�D��=n�
�oKk��n~�6iM
\ No newline at end of file

=== added directory 'dulwich/tests/data/trees/70'
=== added file 'dulwich/tests/data/trees/70/c190eb48fa8bbb50ddc692a17b44cb781af7f6'
Binary files dulwich/tests/data/trees/70/c190eb48fa8bbb50ddc692a17b44cb781af7f6	1970-01-01 00:00:00 +0000 and dulwich/tests/data/trees/70/c190eb48fa8bbb50ddc692a17b44cb781af7f6	2010-04-12 15:07:31 +0000 differ
=== removed file 'dulwich/tests/data/trees/70c190eb48fa8bbb50ddc692a17b44cb781af7f6'
Binary files dulwich/tests/data/trees/70c190eb48fa8bbb50ddc692a17b44cb781af7f6	2008-12-08 22:22:54 +0000 and dulwich/tests/data/trees/70c190eb48fa8bbb50ddc692a17b44cb781af7f6	1970-01-01 00:00:00 +0000 differ
=== added file 'dulwich/tests/test_blackbox.py'
--- dulwich/tests/test_blackbox.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/test_blackbox.py	2010-12-25 23:09:45 +0000
@@ -0,0 +1,67 @@
+# test_blackbox.py -- blackbox tests
+# Copyright (C) 2010 Jelmer Vernooij <jelmer@xxxxxxxxx>
+#
+# 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) a later version.
+#
+# 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.
+
+"""Blackbox tests for Dulwich commands."""
+
+import tempfile
+
+from dulwich.repo import (
+    Repo,
+    )
+from dulwich.tests import (
+    BlackboxTestCase,
+    )
+
+
+class GitReceivePackTests(BlackboxTestCase):
+    """Blackbox tests for dul-receive-pack."""
+
+    def setUp(self):
+        super(GitReceivePackTests, self).setUp()
+        self.path = tempfile.mkdtemp()
+        self.repo = Repo.init(self.path)
+
+    def test_basic(self):
+        process = self.run_command("dul-receive-pack", [self.path])
+        (stdout, stderr) = process.communicate("0000")
+        self.assertEquals('', stderr)
+        self.assertEquals('0000', stdout[-4:])
+        self.assertEquals(0, process.returncode)
+
+    def test_missing_arg(self):
+        process = self.run_command("dul-receive-pack", [])
+        (stdout, stderr) = process.communicate()
+        self.assertEquals('usage: dul-receive-pack <git-dir>\n', stderr)
+        self.assertEquals('', stdout)
+        self.assertEquals(1, process.returncode)
+
+
+class GitUploadPackTests(BlackboxTestCase):
+    """Blackbox tests for dul-upload-pack."""
+
+    def setUp(self):
+        super(GitUploadPackTests, self).setUp()
+        self.path = tempfile.mkdtemp()
+        self.repo = Repo.init(self.path)
+
+    def test_missing_arg(self):
+        process = self.run_command("dul-upload-pack", [])
+        (stdout, stderr) = process.communicate()
+        self.assertEquals('usage: dul-upload-pack <git-dir>\n', stderr)
+        self.assertEquals('', stdout)
+        self.assertEquals(1, process.returncode)

=== modified file 'dulwich/tests/test_client.py'
--- dulwich/tests/test_client.py	2009-03-11 20:27:34 +0000
+++ dulwich/tests/test_client.py	2011-01-05 11:30:32 +0000
@@ -1,43 +1,143 @@
 # test_client.py -- Tests for the git protocol, client side
 # Copyright (C) 2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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
 # 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
-from unittest import TestCase
 
 from dulwich.client import (
     GitClient,
-    )
-
+    TCPGitClient,
+    SubprocessGitClient,
+    SSHGitClient,
+    get_transport_and_path,
+    )
+from dulwich.tests import (
+    TestCase,
+    )
+from dulwich.protocol import (
+    TCP_GIT_PORT,
+    Protocol,
+    )
+
+
+class DummyClient(GitClient):
+    def __init__(self, can_read, read, write):
+        self.can_read = can_read
+        self.read = read
+        self.write = write
+        GitClient.__init__(self)
+
+    def _connect(self, service, path):
+        return Protocol(self.read, self.write), self.can_read
+
+
+# TODO(durin42): add unit-level tests of GitClient
 class GitClientTests(TestCase):
 
     def setUp(self):
+        super(GitClientTests, self).setUp()
         self.rout = StringIO()
         self.rin = StringIO()
-        self.client = GitClient(lambda x: True, self.rin.read, 
-            self.rout.write)
+        self.client = DummyClient(lambda x: True, self.rin.read,
+                                  self.rout.write)
 
     def test_caps(self):
-        self.assertEquals(['multi_ack', 'side-band-64k', 'ofs-delta', 'thin-pack'], self.client._capabilities)
+        self.assertEquals(set(['multi_ack', 'side-band-64k', 'ofs-delta',
+                               'thin-pack']),
+                          set(self.client._fetch_capabilities))
+        self.assertEquals(set(['ofs-delta', 'report-status']),
+                          set(self.client._send_capabilities))
 
     def test_fetch_pack_none(self):
         self.rin.write(
-            "008855dcc6bf963f922e1ed5c4bbaaefcfacef57b1d7 HEAD.multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag\n"
-            "0000")
+            '008855dcc6bf963f922e1ed5c4bbaaefcfacef57b1d7 HEAD.multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag\n'
+            '0000')
         self.rin.seek(0)
-        self.client.fetch_pack("bla", lambda heads: [], None, None, None)
-        self.assertEquals(self.rout.getvalue(), "0000")
+        self.client.fetch_pack('bla', lambda heads: [], None, None, None)
+        self.assertEquals(self.rout.getvalue(), '0000')
+
+    def test_get_transport_and_path_tcp(self):
+        client, path = get_transport_and_path('git://foo.com/bar/baz')
+        self.assertTrue(isinstance(client, TCPGitClient))
+        self.assertEquals('foo.com', client._host)
+        self.assertEquals(TCP_GIT_PORT, client._port)
+        self.assertEqual('/bar/baz', path)
+
+        client, path = get_transport_and_path('git://foo.com:1234/bar/baz')
+        self.assertTrue(isinstance(client, TCPGitClient))
+        self.assertEquals('foo.com', client._host)
+        self.assertEquals(1234, client._port)
+        self.assertEqual('/bar/baz', path)
+
+    def test_get_transport_and_path_ssh_explicit(self):
+        client, path = get_transport_and_path('git+ssh://foo.com/bar/baz')
+        self.assertTrue(isinstance(client, SSHGitClient))
+        self.assertEquals('foo.com', client.host)
+        self.assertEquals(None, client.port)
+        self.assertEquals(None, client.username)
+        self.assertEqual('/bar/baz', path)
+
+        client, path = get_transport_and_path('git+ssh://foo.com:1234/bar/baz')
+        self.assertTrue(isinstance(client, SSHGitClient))
+        self.assertEquals('foo.com', client.host)
+        self.assertEquals(1234, client.port)
+        self.assertEqual('/bar/baz', path)
+
+    def test_get_transport_and_path_ssh_implicit(self):
+        client, path = get_transport_and_path('foo:/bar/baz')
+        self.assertTrue(isinstance(client, SSHGitClient))
+        self.assertEquals('foo', client.host)
+        self.assertEquals(None, client.port)
+        self.assertEquals(None, client.username)
+        self.assertEqual('/bar/baz', path)
+
+        client, path = get_transport_and_path('foo.com:/bar/baz')
+        self.assertTrue(isinstance(client, SSHGitClient))
+        self.assertEquals('foo.com', client.host)
+        self.assertEquals(None, client.port)
+        self.assertEquals(None, client.username)
+        self.assertEqual('/bar/baz', path)
+
+        client, path = get_transport_and_path('user@xxxxxxx:/bar/baz')
+        self.assertTrue(isinstance(client, SSHGitClient))
+        self.assertEquals('foo.com', client.host)
+        self.assertEquals(None, client.port)
+        self.assertEquals('user', client.username)
+        self.assertEqual('/bar/baz', path)
+
+    def test_get_transport_and_path_subprocess(self):
+        client, path = get_transport_and_path('foo.bar/baz')
+        self.assertTrue(isinstance(client, SubprocessGitClient))
+        self.assertEquals('foo.bar/baz', path)
+
+    def test_get_transport_and_path_error(self):
+        self.assertRaises(ValueError, get_transport_and_path, 'foo://bar/baz')
+
+
+class SSHGitClientTests(TestCase):
+
+    def setUp(self):
+        super(SSHGitClientTests, self).setUp()
+        self.client = SSHGitClient('git.samba.org')
+
+    def test_default_command(self):
+        self.assertEquals('git-upload-pack', self.client._get_cmd_path('upload-pack'))
+
+    def test_alternative_command_path(self):
+        self.client.alternative_paths['upload-pack'] = '/usr/lib/git/git-upload-pack'
+        self.assertEquals('/usr/lib/git/git-upload-pack', self.client._get_cmd_path('upload-pack'))
+

=== added file 'dulwich/tests/test_diff_tree.py'
--- dulwich/tests/test_diff_tree.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/test_diff_tree.py	2010-12-19 15:56:03 +0000
@@ -0,0 +1,671 @@
+# test_diff_tree.py -- Tests for file and tree diff utilities.
+# Copyright (C) 2010 Google, Inc.
+#
+# 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; either version 2
+# or (at your option) a 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.
+
+"""Tests for file and tree diff utilities."""
+
+from dulwich.diff_tree import (
+    CHANGE_MODIFY,
+    CHANGE_RENAME,
+    CHANGE_COPY,
+    CHANGE_UNCHANGED,
+    TreeChange,
+    _merge_entries,
+    _merge_entries_py,
+    tree_changes,
+    _count_blocks,
+    _count_blocks_py,
+    _similarity_score,
+    _tree_change_key,
+    RenameDetector,
+    _is_tree,
+    _is_tree_py
+    )
+from dulwich.index import (
+    commit_tree,
+    )
+from dulwich._compat import (
+    permutations,
+    )
+from dulwich.object_store import (
+    MemoryObjectStore,
+    )
+from dulwich.objects import (
+    ShaFile,
+    Blob,
+    TreeEntry,
+    Tree,
+    )
+from dulwich.tests import (
+    TestCase,
+    )
+from dulwich.tests.utils import (
+    make_object,
+    functest_builder,
+    ext_functest_builder,
+    )
+
+# Shorthand mode for Files.
+F = 0100644
+
+
+class DiffTestCase(TestCase):
+
+    def setUp(self):
+        super(DiffTestCase, self).setUp()
+        self.store = MemoryObjectStore()
+        self.empty_tree = self.commit_tree([])
+
+    def commit_tree(self, entries):
+        commit_blobs = []
+        for entry in entries:
+            if len(entry) == 2:
+                path, obj = entry
+                mode = F
+            else:
+                path, obj, mode = entry
+            if isinstance(obj, Blob):
+                self.store.add_object(obj)
+                sha = obj.id
+            else:
+                sha = obj
+            commit_blobs.append((path, sha, mode))
+        return self.store[commit_tree(self.store, commit_blobs)]
+
+
+class TreeChangesTest(DiffTestCase):
+
+    def assertMergeFails(self, merge_entries, name, mode, sha):
+        t = Tree()
+        t[name] = (mode, sha)
+        self.assertRaises(TypeError, merge_entries, '', t, t)
+
+    def _do_test_merge_entries(self, merge_entries):
+        blob_a1 = make_object(Blob, data='a1')
+        blob_a2 = make_object(Blob, data='a2')
+        blob_b1 = make_object(Blob, data='b1')
+        blob_c2 = make_object(Blob, data='c2')
+        tree1 = self.commit_tree([('a', blob_a1, 0100644),
+                                  ('b', blob_b1, 0100755)])
+        tree2 = self.commit_tree([('a', blob_a2, 0100644),
+                                  ('c', blob_c2, 0100755)])
+
+        self.assertEqual([], merge_entries('', self.empty_tree,
+                                           self.empty_tree))
+        self.assertEqual([
+          ((None, None, None), ('a', 0100644, blob_a1.id)),
+          ((None, None, None), ('b', 0100755, blob_b1.id)),
+          ], merge_entries('', self.empty_tree, tree1))
+        self.assertEqual([
+          ((None, None, None), ('x/a', 0100644, blob_a1.id)),
+          ((None, None, None), ('x/b', 0100755, blob_b1.id)),
+          ], merge_entries('x', self.empty_tree, tree1))
+
+        self.assertEqual([
+          (('a', 0100644, blob_a2.id), (None, None, None)),
+          (('c', 0100755, blob_c2.id), (None, None, None)),
+          ], merge_entries('', tree2, self.empty_tree))
+
+        self.assertEqual([
+          (('a', 0100644, blob_a1.id), ('a', 0100644, blob_a2.id)),
+          (('b', 0100755, blob_b1.id), (None, None, None)),
+          ((None, None, None), ('c', 0100755, blob_c2.id)),
+          ], merge_entries('', tree1, tree2))
+
+        self.assertEqual([
+          (('a', 0100644, blob_a2.id), ('a', 0100644, blob_a1.id)),
+          ((None, None, None), ('b', 0100755, blob_b1.id)),
+          (('c', 0100755, blob_c2.id), (None, None, None)),
+          ], merge_entries('', tree2, tree1))
+
+        self.assertMergeFails(merge_entries, 0xdeadbeef, 0100644, '1' * 40)
+        self.assertMergeFails(merge_entries, 'a', 'deadbeef', '1' * 40)
+        self.assertMergeFails(merge_entries, 'a', 0100644, 0xdeadbeef)
+
+    test_merge_entries = functest_builder(_do_test_merge_entries,
+                                          _merge_entries_py)
+    test_merge_entries_extension = ext_functest_builder(_do_test_merge_entries,
+                                                        _merge_entries)
+
+    def _do_test_is_tree(self, is_tree):
+        self.assertFalse(is_tree(TreeEntry(None, None, None)))
+        self.assertFalse(is_tree(TreeEntry('a', 0100644, 'a' * 40)))
+        self.assertFalse(is_tree(TreeEntry('a', 0100755, 'a' * 40)))
+        self.assertFalse(is_tree(TreeEntry('a', 0120000, 'a' * 40)))
+        self.assertTrue(is_tree(TreeEntry('a', 0040000, 'a' * 40)))
+        self.assertRaises(TypeError, is_tree, TreeEntry('a', 'x', 'a' * 40))
+        self.assertRaises(AttributeError, is_tree, 1234)
+
+    test_is_tree = functest_builder(_do_test_is_tree, _is_tree_py)
+    test_is_tree_extension = ext_functest_builder(_do_test_is_tree, _is_tree)
+
+    def assertChangesEqual(self, expected, tree1, tree2, **kwargs):
+        actual = list(tree_changes(self.store, tree1.id, tree2.id, **kwargs))
+        self.assertEqual(expected, actual)
+
+    # For brevity, the following tests use tuples instead of TreeEntry objects.
+
+    def test_tree_changes_empty(self):
+        self.assertChangesEqual([], self.empty_tree, self.empty_tree)
+
+    def test_tree_changes_no_changes(self):
+        blob = make_object(Blob, data='blob')
+        tree = self.commit_tree([('a', blob), ('b/c', blob)])
+        self.assertChangesEqual([], self.empty_tree, self.empty_tree)
+        self.assertChangesEqual([], tree, tree)
+        self.assertChangesEqual(
+          [TreeChange(CHANGE_UNCHANGED, ('a', F, blob.id), ('a', F, blob.id)),
+           TreeChange(CHANGE_UNCHANGED, ('b/c', F, blob.id),
+                      ('b/c', F, blob.id))],
+          tree, tree, want_unchanged=True)
+
+    def test_tree_changes_add_delete(self):
+        blob_a = make_object(Blob, data='a')
+        blob_b = make_object(Blob, data='b')
+        tree = self.commit_tree([('a', blob_a, 0100644),
+                                 ('x/b', blob_b, 0100755)])
+        self.assertChangesEqual(
+          [TreeChange.add(('a', 0100644, blob_a.id)),
+           TreeChange.add(('x/b', 0100755, blob_b.id))],
+          self.empty_tree, tree)
+        self.assertChangesEqual(
+          [TreeChange.delete(('a', 0100644, blob_a.id)),
+           TreeChange.delete(('x/b', 0100755, blob_b.id))],
+          tree, self.empty_tree)
+
+    def test_tree_changes_modify_contents(self):
+        blob_a1 = make_object(Blob, data='a1')
+        blob_a2 = make_object(Blob, data='a2')
+        tree1 = self.commit_tree([('a', blob_a1)])
+        tree2 = self.commit_tree([('a', blob_a2)])
+        self.assertChangesEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', F, blob_a1.id),
+                      ('a', F, blob_a2.id))], tree1, tree2)
+
+    def test_tree_changes_modify_mode(self):
+        blob_a = make_object(Blob, data='a')
+        tree1 = self.commit_tree([('a', blob_a, 0100644)])
+        tree2 = self.commit_tree([('a', blob_a, 0100755)])
+        self.assertChangesEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', 0100644, blob_a.id),
+                      ('a', 0100755, blob_a.id))], tree1, tree2)
+
+    def test_tree_changes_change_type(self):
+        blob_a1 = make_object(Blob, data='a')
+        blob_a2 = make_object(Blob, data='/foo/bar')
+        tree1 = self.commit_tree([('a', blob_a1, 0100644)])
+        tree2 = self.commit_tree([('a', blob_a2, 0120000)])
+        self.assertChangesEqual(
+          [TreeChange.delete(('a', 0100644, blob_a1.id)),
+           TreeChange.add(('a', 0120000, blob_a2.id))],
+          tree1, tree2)
+
+    def test_tree_changes_to_tree(self):
+        blob_a = make_object(Blob, data='a')
+        blob_x = make_object(Blob, data='x')
+        tree1 = self.commit_tree([('a', blob_a)])
+        tree2 = self.commit_tree([('a/x', blob_x)])
+        self.assertChangesEqual(
+          [TreeChange.delete(('a', F, blob_a.id)),
+           TreeChange.add(('a/x', F, blob_x.id))],
+          tree1, tree2)
+
+    def test_tree_changes_complex(self):
+        blob_a_1 = make_object(Blob, data='a1_1')
+        blob_bx1_1 = make_object(Blob, data='bx1_1')
+        blob_bx2_1 = make_object(Blob, data='bx2_1')
+        blob_by1_1 = make_object(Blob, data='by1_1')
+        blob_by2_1 = make_object(Blob, data='by2_1')
+        tree1 = self.commit_tree([
+          ('a', blob_a_1),
+          ('b/x/1', blob_bx1_1),
+          ('b/x/2', blob_bx2_1),
+          ('b/y/1', blob_by1_1),
+          ('b/y/2', blob_by2_1),
+          ])
+
+        blob_a_2 = make_object(Blob, data='a1_2')
+        blob_bx1_2 = blob_bx1_1
+        blob_by_2 = make_object(Blob, data='by_2')
+        blob_c_2 = make_object(Blob, data='c_2')
+        tree2 = self.commit_tree([
+          ('a', blob_a_2),
+          ('b/x/1', blob_bx1_2),
+          ('b/y', blob_by_2),
+          ('c', blob_c_2),
+          ])
+
+        self.assertChangesEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', F, blob_a_1.id),
+                      ('a', F, blob_a_2.id)),
+           TreeChange.delete(('b/x/2', F, blob_bx2_1.id)),
+           TreeChange.add(('b/y', F, blob_by_2.id)),
+           TreeChange.delete(('b/y/1', F, blob_by1_1.id)),
+           TreeChange.delete(('b/y/2', F, blob_by2_1.id)),
+           TreeChange.add(('c', F, blob_c_2.id))],
+          tree1, tree2)
+
+    def test_tree_changes_name_order(self):
+        blob = make_object(Blob, data='a')
+        tree1 = self.commit_tree([('a', blob), ('a.', blob), ('a..', blob)])
+        # Tree order is the reverse of this, so if we used tree order, 'a..'
+        # would not be merged.
+        tree2 = self.commit_tree([('a/x', blob), ('a./x', blob), ('a..', blob)])
+
+        self.assertChangesEqual(
+          [TreeChange.delete(('a', F, blob.id)),
+           TreeChange.add(('a/x', F, blob.id)),
+           TreeChange.delete(('a.', F, blob.id)),
+           TreeChange.add(('a./x', F, blob.id))],
+          tree1, tree2)
+
+    def test_tree_changes_prune(self):
+        blob_a1 = make_object(Blob, data='a1')
+        blob_a2 = make_object(Blob, data='a2')
+        blob_x = make_object(Blob, data='x')
+        tree1 = self.commit_tree([('a', blob_a1), ('b/x', blob_x)])
+        tree2 = self.commit_tree([('a', blob_a2), ('b/x', blob_x)])
+        # Remove identical items so lookups will fail unless we prune.
+        subtree = self.store[tree1['b'][1]]
+        for entry in subtree.iteritems():
+            del self.store[entry.sha]
+        del self.store[subtree.id]
+
+        self.assertChangesEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', F, blob_a1.id),
+                      ('a', F, blob_a2.id))],
+          tree1, tree2)
+
+
+class RenameDetectionTest(DiffTestCase):
+
+    def _do_test_count_blocks(self, count_blocks):
+        blob = make_object(Blob, data='a\nb\na\n')
+        self.assertEqual({hash('a\n'): 4, hash('b\n'): 2}, count_blocks(blob))
+
+    test_count_blocks = functest_builder(_do_test_count_blocks,
+                                         _count_blocks_py)
+    test_count_blocks_extension = ext_functest_builder(_do_test_count_blocks,
+                                                       _count_blocks)
+
+    def _do_test_count_blocks_no_newline(self, count_blocks):
+        blob = make_object(Blob, data='a\na')
+        self.assertEqual({hash('a\n'): 2, hash('a'): 1}, _count_blocks(blob))
+
+    test_count_blocks_no_newline = functest_builder(
+      _do_test_count_blocks_no_newline, _count_blocks_py)
+    test_count_blocks_no_newline_extension = ext_functest_builder(
+       _do_test_count_blocks_no_newline, _count_blocks)
+
+    def _do_test_count_blocks_chunks(self, count_blocks):
+        blob = ShaFile.from_raw_chunks(Blob.type_num, ['a\nb', '\na\n'])
+        self.assertEqual({hash('a\n'): 4, hash('b\n'): 2}, _count_blocks(blob))
+
+    test_count_blocks_chunks = functest_builder(_do_test_count_blocks_chunks,
+                                                _count_blocks_py)
+    test_count_blocks_chunks_extension = ext_functest_builder(
+      _do_test_count_blocks_chunks, _count_blocks)
+
+    def _do_test_count_blocks_long_lines(self, count_blocks):
+        a = 'a' * 64
+        data = a + 'xxx\ny\n' + a + 'zzz\n'
+        blob = make_object(Blob, data=data)
+        self.assertEqual({hash('a' * 64): 128, hash('xxx\n'): 4, hash('y\n'): 2,
+                          hash('zzz\n'): 4},
+                         _count_blocks(blob))
+
+    test_count_blocks_long_lines = functest_builder(
+      _do_test_count_blocks_long_lines, _count_blocks_py)
+    test_count_blocks_long_lines_extension = ext_functest_builder(
+      _do_test_count_blocks_long_lines, _count_blocks)
+
+    def assertSimilar(self, expected_score, blob1, blob2):
+        self.assertEqual(expected_score, _similarity_score(blob1, blob2))
+        self.assertEqual(expected_score, _similarity_score(blob2, blob1))
+
+    def test_similarity_score(self):
+        blob0 = make_object(Blob, data='')
+        blob1 = make_object(Blob, data='ab\ncd\ncd\n')
+        blob2 = make_object(Blob, data='ab\n')
+        blob3 = make_object(Blob, data='cd\n')
+        blob4 = make_object(Blob, data='cd\ncd\n')
+
+        self.assertSimilar(100, blob0, blob0)
+        self.assertSimilar(0, blob0, blob1)
+        self.assertSimilar(33, blob1, blob2)
+        self.assertSimilar(33, blob1, blob3)
+        self.assertSimilar(66, blob1, blob4)
+        self.assertSimilar(0, blob2, blob3)
+        self.assertSimilar(50, blob3, blob4)
+
+    def test_similarity_score_cache(self):
+        blob1 = make_object(Blob, data='ab\ncd\n')
+        blob2 = make_object(Blob, data='ab\n')
+
+        block_cache = {}
+        self.assertEqual(
+          50, _similarity_score(blob1, blob2, block_cache=block_cache))
+        self.assertEqual(set([blob1.id, blob2.id]), set(block_cache))
+
+        def fail_chunks():
+            self.fail('Unexpected call to as_raw_chunks()')
+
+        blob1.as_raw_chunks = blob2.as_raw_chunks = fail_chunks
+        blob1.raw_length = lambda: 6
+        blob2.raw_length = lambda: 3
+        self.assertEqual(
+          50, _similarity_score(blob1, blob2, block_cache=block_cache))
+
+    def test_tree_entry_sort(self):
+        sha = 'abcd' * 10
+        expected_entries = [
+          TreeChange.add(TreeEntry('aaa', F, sha)),
+          TreeChange(CHANGE_COPY, TreeEntry('bbb', F, sha),
+                     TreeEntry('aab', F, sha)),
+          TreeChange(CHANGE_MODIFY, TreeEntry('bbb', F, sha),
+                     TreeEntry('bbb', F, 'dabc' * 10)),
+          TreeChange(CHANGE_RENAME, TreeEntry('bbc', F, sha),
+                     TreeEntry('ddd', F, sha)),
+          TreeChange.delete(TreeEntry('ccc', F, sha)),
+          ]
+
+        for perm in permutations(expected_entries):
+            self.assertEqual(expected_entries,
+                             sorted(perm, key=_tree_change_key))
+
+    def detect_renames(self, tree1, tree2, **kwargs):
+        detector = RenameDetector(self.store, tree1.id, tree2.id, **kwargs)
+        return detector.changes_with_renames()
+
+    def test_no_renames(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob2 = make_object(Blob, data='a\nb\ne\nf\n')
+        blob3 = make_object(Blob, data='a\nb\ng\nh\n')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('a', blob1), ('b', blob3)])
+        self.assertEqual(
+          [TreeChange(CHANGE_MODIFY, ('b', F, blob2.id), ('b', F, blob3.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_exact_rename_one_to_one(self):
+        blob1 = make_object(Blob, data='1')
+        blob2 = make_object(Blob, data='2')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('c', blob1), ('d', blob2)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob1.id)),
+           TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('d', F, blob2.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_exact_rename_split_different_type(self):
+        blob = make_object(Blob, data='/foo')
+        tree1 = self.commit_tree([('a', blob, 0100644)])
+        tree2 = self.commit_tree([('a', blob, 0120000)])
+        self.assertEqual(
+          [TreeChange.add(('a', 0120000, blob.id)),
+           TreeChange.delete(('a', 0100644, blob.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_exact_rename_and_different_type(self):
+        blob1 = make_object(Blob, data='1')
+        blob2 = make_object(Blob, data='2')
+        tree1 = self.commit_tree([('a', blob1)])
+        tree2 = self.commit_tree([('a', blob2, 0120000), ('b', blob1)])
+        self.assertEqual(
+          [TreeChange.add(('a', 0120000, blob2.id)),
+           TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob1.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_exact_rename_one_to_many(self):
+        blob = make_object(Blob, data='1')
+        tree1 = self.commit_tree([('a', blob)])
+        tree2 = self.commit_tree([('b', blob), ('c', blob)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob.id), ('b', F, blob.id)),
+           TreeChange(CHANGE_COPY, ('a', F, blob.id), ('c', F, blob.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_exact_rename_many_to_one(self):
+        blob = make_object(Blob, data='1')
+        tree1 = self.commit_tree([('a', blob), ('b', blob)])
+        tree2 = self.commit_tree([('c', blob)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob.id), ('c', F, blob.id)),
+           TreeChange.delete(('b', F, blob.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_exact_rename_many_to_many(self):
+        blob = make_object(Blob, data='1')
+        tree1 = self.commit_tree([('a', blob), ('b', blob)])
+        tree2 = self.commit_tree([('c', blob), ('d', blob), ('e', blob)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob.id), ('c', F, blob.id)),
+           TreeChange(CHANGE_COPY, ('a', F, blob.id), ('e', F, blob.id)),
+           TreeChange(CHANGE_RENAME, ('b', F, blob.id), ('d', F, blob.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_rename_threshold(self):
+        blob1 = make_object(Blob, data='a\nb\nc\n')
+        blob2 = make_object(Blob, data='a\nb\nd\n')
+        tree1 = self.commit_tree([('a', blob1)])
+        tree2 = self.commit_tree([('b', blob2)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2, rename_threshold=50))
+        self.assertEqual(
+          [TreeChange.delete(('a', F, blob1.id)),
+           TreeChange.add(('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2, rename_threshold=75))
+
+    def test_content_rename_max_files(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd')
+        blob4 = make_object(Blob, data='a\nb\nc\ne\n')
+        blob2 = make_object(Blob, data='e\nf\ng\nh\n')
+        blob3 = make_object(Blob, data='e\nf\ng\ni\n')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('c', blob3), ('d', blob4)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('d', F, blob4.id)),
+           TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('c', F, blob3.id))],
+          self.detect_renames(tree1, tree2))
+        self.assertEqual(
+          [TreeChange.delete(('a', F, blob1.id)),
+           TreeChange.delete(('b', F, blob2.id)),
+           TreeChange.add(('c', F, blob3.id)),
+           TreeChange.add(('d', F, blob4.id))],
+          self.detect_renames(tree1, tree2, max_files=1))
+
+    def test_content_rename_one_to_one(self):
+        b11 = make_object(Blob, data='a\nb\nc\nd\n')
+        b12 = make_object(Blob, data='a\nb\nc\ne\n')
+        b21 = make_object(Blob, data='e\nf\ng\n\h')
+        b22 = make_object(Blob, data='e\nf\ng\n\i')
+        tree1 = self.commit_tree([('a', b11), ('b', b21)])
+        tree2 = self.commit_tree([('c', b12), ('d', b22)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, b11.id), ('c', F, b12.id)),
+           TreeChange(CHANGE_RENAME, ('b', F, b21.id), ('d', F, b22.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_content_rename_one_to_one_ordering(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\ne\nf\n')
+        blob2 = make_object(Blob, data='a\nb\nc\nd\ng\nh\n')
+        # 6/10 match to blob1, 8/10 match to blob2
+        blob3 = make_object(Blob, data='a\nb\nc\nd\ng\ni\n')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('c', blob3)])
+        self.assertEqual(
+          [TreeChange.delete(('a', F, blob1.id)),
+           TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('c', F, blob3.id))],
+          self.detect_renames(tree1, tree2))
+
+        tree3 = self.commit_tree([('a', blob2), ('b', blob1)])
+        tree4 = self.commit_tree([('c', blob3)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob2.id), ('c', F, blob3.id)),
+           TreeChange.delete(('b', F, blob1.id))],
+          self.detect_renames(tree3, tree4))
+
+    def test_content_rename_one_to_many(self):
+        blob1 = make_object(Blob, data='aa\nb\nc\nd\ne\n')
+        blob2 = make_object(Blob, data='ab\nb\nc\nd\ne\n')  # 8/11 match
+        blob3 = make_object(Blob, data='aa\nb\nc\nd\nf\n')  # 9/11 match
+        tree1 = self.commit_tree([('a', blob1)])
+        tree2 = self.commit_tree([('b', blob2), ('c', blob3)])
+        self.assertEqual(
+          [TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id)),
+           TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob3.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_content_rename_many_to_one(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
+        blob3 = make_object(Blob, data='a\nb\nc\nf\n')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('c', blob3)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob3.id)),
+           TreeChange.delete(('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_content_rename_many_to_many(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
+        blob3 = make_object(Blob, data='a\nb\nc\nf\n')
+        blob4 = make_object(Blob, data='a\nb\nc\ng\n')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('c', blob3), ('d', blob4)])
+        # TODO(dborowitz): Distribute renames rather than greedily choosing
+        # copies.
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('c', F, blob3.id)),
+           TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('d', F, blob4.id)),
+           TreeChange.delete(('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2))
+
+    def test_content_rename_gitlink(self):
+        blob1 = make_object(Blob, data='blob1')
+        blob2 = make_object(Blob, data='blob2')
+        link1 = '1' * 40
+        link2 = '2' * 40
+        tree1 = self.commit_tree([('a', blob1), ('b', link1, 0160000)])
+        tree2 = self.commit_tree([('c', blob2), ('d', link2, 0160000)])
+        self.assertEqual(
+          [TreeChange.delete(('a', 0100644, blob1.id)),
+           TreeChange.delete(('b', 0160000, link1)),
+           TreeChange.add(('c', 0100644, blob2.id)),
+           TreeChange.add(('d', 0160000, link2))],
+          self.detect_renames(tree1, tree2))
+
+    def test_exact_rename_swap(self):
+        blob1 = make_object(Blob, data='1')
+        blob2 = make_object(Blob, data='2')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('a', blob2), ('b', blob1)])
+        self.assertEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)),
+           TreeChange(CHANGE_MODIFY, ('b', F, blob2.id), ('b', F, blob1.id))],
+          self.detect_renames(tree1, tree2))
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob1.id)),
+           TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('a', F, blob2.id))],
+          self.detect_renames(tree1, tree2, rewrite_threshold=50))
+
+    def test_content_rename_swap(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob2 = make_object(Blob, data='e\nf\ng\nh\n')
+        blob3 = make_object(Blob, data='a\nb\nc\ne\n')
+        blob4 = make_object(Blob, data='e\nf\ng\ni\n')
+        tree1 = self.commit_tree([('a', blob1), ('b', blob2)])
+        tree2 = self.commit_tree([('a', blob4), ('b', blob3)])
+        self.assertEqual(
+          [TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob3.id)),
+           TreeChange(CHANGE_RENAME, ('b', F, blob2.id), ('a', F, blob4.id))],
+          self.detect_renames(tree1, tree2, rewrite_threshold=60))
+
+    def test_rewrite_threshold(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
+        blob3 = make_object(Blob, data='a\nb\nf\ng\n')
+
+        tree1 = self.commit_tree([('a', blob1)])
+        tree2 = self.commit_tree([('a', blob3), ('b', blob2)])
+
+        no_renames = [
+          TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob3.id)),
+          TreeChange.add(('b', F, blob2.id))]
+        self.assertEqual(
+          no_renames, self.detect_renames(tree1, tree2))
+        self.assertEqual(
+          no_renames, self.detect_renames(tree1, tree2, rewrite_threshold=40))
+        self.assertEqual(
+          [TreeChange.add(('a', F, blob3.id)),
+           TreeChange(CHANGE_RENAME, ('a', F, blob1.id), ('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2, rewrite_threshold=80))
+
+    def test_find_copies_harder_exact(self):
+        blob = make_object(Blob, data='blob')
+        tree1 = self.commit_tree([('a', blob)])
+        tree2 = self.commit_tree([('a', blob), ('b', blob)])
+        self.assertEqual([TreeChange.add(('b', F, blob.id))],
+                         self.detect_renames(tree1, tree2))
+        self.assertEqual(
+          [TreeChange(CHANGE_COPY, ('a', F, blob.id), ('b', F, blob.id))],
+          self.detect_renames(tree1, tree2, find_copies_harder=True))
+
+    def test_find_copies_harder_content(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
+        tree1 = self.commit_tree([('a', blob1)])
+        tree2 = self.commit_tree([('a', blob1), ('b', blob2)])
+        self.assertEqual([TreeChange.add(('b', F, blob2.id))],
+                         self.detect_renames(tree1, tree2))
+        self.assertEqual(
+          [TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2, find_copies_harder=True))
+
+    def test_find_copies_harder_modify(self):
+        blob1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob2 = make_object(Blob, data='a\nb\nc\ne\n')
+        tree1 = self.commit_tree([('a', blob1)])
+        tree2 = self.commit_tree([('a', blob2), ('b', blob2)])
+        self.assertEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)),
+           TreeChange.add(('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2))
+        self.assertEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', F, blob1.id), ('a', F, blob2.id)),
+           TreeChange(CHANGE_COPY, ('a', F, blob1.id), ('b', F, blob2.id))],
+          self.detect_renames(tree1, tree2, find_copies_harder=True))
+
+    def test_find_copies_harder_with_rewrites(self):
+        blob_a1 = make_object(Blob, data='a\nb\nc\nd\n')
+        blob_a2 = make_object(Blob, data='f\ng\nh\ni\n')
+        blob_b2 = make_object(Blob, data='a\nb\nc\ne\n')
+        tree1 = self.commit_tree([('a', blob_a1)])
+        tree2 = self.commit_tree([('a', blob_a2), ('b', blob_b2)])
+        self.assertEqual(
+          [TreeChange(CHANGE_MODIFY, ('a', F, blob_a1.id),
+                      ('a', F, blob_a2.id)),
+           TreeChange(CHANGE_COPY, ('a', F, blob_a1.id), ('b', F, blob_b2.id))],
+          self.detect_renames(tree1, tree2, find_copies_harder=True))
+        self.assertEqual(
+          [TreeChange.add(('a', F, blob_a2.id)),
+           TreeChange(CHANGE_RENAME, ('a', F, blob_a1.id),
+                      ('b', F, blob_b2.id))],
+          self.detect_renames(tree1, tree2, rewrite_threshold=50,
+                              find_copies_harder=True))

=== added file 'dulwich/tests/test_fastexport.py'
--- dulwich/tests/test_fastexport.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/test_fastexport.py	2010-12-12 05:15:03 +0000
@@ -0,0 +1,202 @@
+# test_fastexport.py -- Fast export/import functionality
+# Copyright (C) 2010 Jelmer Vernooij <jelmer@xxxxxxxxx>
+#
+# 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 dulwich.object_store import (
+    MemoryObjectStore,
+    )
+from dulwich.objects import (
+    Blob,
+    Commit,
+    Tree,
+    )
+from dulwich.repo import (
+    MemoryRepo,
+    )
+from dulwich.tests import (
+    TestCase,
+    TestSkipped,
+    )
+
+
+class GitFastExporterTests(TestCase):
+    """Tests for the GitFastExporter tests."""
+
+    def setUp(self):
+        super(GitFastExporterTests, self).setUp()
+        self.store = MemoryObjectStore()
+        self.stream = StringIO()
+        try:
+            from dulwich.fastexport import GitFastExporter
+        except ImportError:
+            raise TestSkipped("python-fastimport not available")
+        self.fastexporter = GitFastExporter(self.stream, self.store)
+
+    def test_emit_blob(self):
+        b = Blob()
+        b.data = "fooBAR"
+        self.fastexporter.emit_blob(b)
+        self.assertEquals('blob\nmark :1\ndata 6\nfooBAR\n',
+            self.stream.getvalue())
+
+    def test_emit_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
+        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.fastexporter.emit_commit(c, "refs/heads/master")
+        self.assertEquals("""blob
+mark :1
+data 3
+FOO
+commit refs/heads/master
+mark :2
+author Jelmer <jelmer@host> 1271345553 +0000
+committer Jelmer <jelmer@host> 1271345553 +0000
+data 3
+msg
+M 644 1 foo
+""", self.stream.getvalue())
+
+
+class GitImportProcessorTests(TestCase):
+    """Tests for the GitImportProcessor tests."""
+
+    def setUp(self):
+        super(GitImportProcessorTests, self).setUp()
+        self.repo = MemoryRepo()
+        try:
+            from dulwich.fastexport import GitImportProcessor
+        except ImportError:
+            raise TestSkipped("python-fastimport not available")
+        self.processor = GitImportProcessor(self.repo)
+
+    def test_commit_handler(self):
+        from fastimport import commands
+        cmd = commands.CommitCommand("refs/heads/foo", "mrkr",
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            "FOO", None, [], [])
+        self.processor.commit_handler(cmd)
+        commit = self.repo[self.processor.last_commit]
+        self.assertEquals("Jelmer <jelmer@xxxxxxxxx>", commit.author)
+        self.assertEquals("Jelmer <jelmer@xxxxxxxxx>", commit.committer)
+        self.assertEquals("FOO", commit.message)
+        self.assertEquals([], commit.parents)
+        self.assertEquals(432432432.0, commit.commit_time)
+        self.assertEquals(432432432.0, commit.author_time)
+        self.assertEquals(3600, commit.commit_timezone)
+        self.assertEquals(3600, commit.author_timezone)
+        self.assertEquals(commit, self.repo["refs/heads/foo"])
+
+    def test_import_stream(self):
+        markers = self.processor.import_stream(StringIO("""blob
+mark :1
+data 11
+text for a
+
+commit refs/heads/master
+mark :2
+committer Joe Foo <joe@xxxxxxx> 1288287382 +0000
+data 20
+<The commit message>
+M 100644 :1 a
+
+"""))
+        self.assertEquals(2, len(markers))
+        self.assertTrue(isinstance(self.repo[markers["1"]], Blob))
+        self.assertTrue(isinstance(self.repo[markers["2"]], Commit))
+
+    def test_file_add(self):
+        from fastimport import commands
+        cmd = commands.BlobCommand("23", "data")
+        self.processor.blob_handler(cmd)
+        cmd = commands.CommitCommand("refs/heads/foo", "mrkr",
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            "FOO", None, [], [commands.FileModifyCommand("path", 0100644, ":23", None)])
+        self.processor.commit_handler(cmd)
+        commit = self.repo[self.processor.last_commit]
+        self.assertEquals([
+            ('path', 0100644, '6320cd248dd8aeaab759d5871f8781b5c0505172')],
+            self.repo[commit.tree].items())
+
+    def simple_commit(self):
+        from fastimport import commands
+        cmd = commands.BlobCommand("23", "data")
+        self.processor.blob_handler(cmd)
+        cmd = commands.CommitCommand("refs/heads/foo", "mrkr",
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            "FOO", None, [], [commands.FileModifyCommand("path", 0100644, ":23", None)])
+        self.processor.commit_handler(cmd)
+        commit = self.repo[self.processor.last_commit]
+        return commit
+
+    def make_file_commit(self, file_cmds):
+        """Create a trivial commit with the specified file commands.
+
+        :param file_cmds: File commands to run.
+        :return: The created commit object
+        """
+        from fastimport import commands
+        cmd = commands.CommitCommand("refs/heads/foo", "mrkr",
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            ("Jelmer", "jelmer@xxxxxxxxx", 432432432.0, 3600),
+            "FOO", None, [], file_cmds)
+        self.processor.commit_handler(cmd)
+        return self.repo[self.processor.last_commit]
+
+    def test_file_copy(self):
+        from fastimport import commands
+        self.simple_commit()
+        commit = self.make_file_commit([commands.FileCopyCommand("path", "new_path")])
+        self.assertEquals([
+            ('new_path', 0100644, '6320cd248dd8aeaab759d5871f8781b5c0505172'),
+            ('path', 0100644, '6320cd248dd8aeaab759d5871f8781b5c0505172'),
+            ], self.repo[commit.tree].items())
+
+    def test_file_move(self):
+        from fastimport import commands
+        self.simple_commit()
+        commit = self.make_file_commit([commands.FileRenameCommand("path", "new_path")])
+        self.assertEquals([
+            ('new_path', 0100644, '6320cd248dd8aeaab759d5871f8781b5c0505172'),
+            ], self.repo[commit.tree].items())
+
+    def test_file_delete(self):
+        from fastimport import commands
+        self.simple_commit()
+        commit = self.make_file_commit([commands.FileDeleteCommand("path")])
+        self.assertEquals([], self.repo[commit.tree].items())
+
+    def test_file_deleteall(self):
+        from fastimport import commands
+        self.simple_commit()
+        commit = self.make_file_commit([commands.FileDeleteAllCommand()])
+        self.assertEquals([], self.repo[commit.tree].items())

=== added file 'dulwich/tests/test_file.py'
--- dulwich/tests/test_file.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/test_file.py	2010-07-26 17:43:17 +0000
@@ -0,0 +1,210 @@
+# test_file.py -- Test for git files
+# Copyright (C) 2010 Google, Inc.
+#
+# 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) a 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.
+
+import errno
+import os
+import shutil
+import sys
+import tempfile
+
+from dulwich.file import GitFile, fancy_rename
+from dulwich.tests import (
+    TestCase,
+    TestSkipped,
+    )
+
+
+class FancyRenameTests(TestCase):
+
+    def setUp(self):
+        super(FancyRenameTests, self).setUp()
+        self._tempdir = tempfile.mkdtemp()
+        self.foo = self.path('foo')
+        self.bar = self.path('bar')
+        self.create(self.foo, 'foo contents')
+
+    def tearDown(self):
+        shutil.rmtree(self._tempdir)
+        super(FancyRenameTests, self).tearDown()
+
+    def path(self, filename):
+        return os.path.join(self._tempdir, filename)
+
+    def create(self, path, contents):
+        f = open(path, 'wb')
+        f.write(contents)
+        f.close()
+
+    def test_no_dest_exists(self):
+        self.assertFalse(os.path.exists(self.bar))
+        fancy_rename(self.foo, self.bar)
+        self.assertFalse(os.path.exists(self.foo))
+
+        new_f = open(self.bar, 'rb')
+        self.assertEquals('foo contents', new_f.read())
+        new_f.close()
+         
+    def test_dest_exists(self):
+        self.create(self.bar, 'bar contents')
+        fancy_rename(self.foo, self.bar)
+        self.assertFalse(os.path.exists(self.foo))
+
+        new_f = open(self.bar, 'rb')
+        self.assertEquals('foo contents', new_f.read())
+        new_f.close()
+
+    def test_dest_opened(self):
+        if sys.platform != "win32":
+            raise TestSkipped("platform allows overwriting open files")
+        self.create(self.bar, 'bar contents')
+        dest_f = open(self.bar, 'rb')
+        self.assertRaises(OSError, fancy_rename, self.foo, self.bar)
+        dest_f.close()
+        self.assertTrue(os.path.exists(self.path('foo')))
+
+        new_f = open(self.foo, 'rb')
+        self.assertEquals('foo contents', new_f.read())
+        new_f.close()
+
+        new_f = open(self.bar, 'rb')
+        self.assertEquals('bar contents', new_f.read())
+        new_f.close()
+
+
+class GitFileTests(TestCase):
+
+    def setUp(self):
+        super(GitFileTests, self).setUp()
+        self._tempdir = tempfile.mkdtemp()
+        f = open(self.path('foo'), 'wb')
+        f.write('foo contents')
+        f.close()
+
+    def tearDown(self):
+        shutil.rmtree(self._tempdir)
+        super(GitFileTests, self).tearDown()
+
+    def path(self, filename):
+        return os.path.join(self._tempdir, filename)
+
+    def test_invalid(self):
+        foo = self.path('foo')
+        self.assertRaises(IOError, GitFile, foo, mode='r')
+        self.assertRaises(IOError, GitFile, foo, mode='ab')
+        self.assertRaises(IOError, GitFile, foo, mode='r+b')
+        self.assertRaises(IOError, GitFile, foo, mode='w+b')
+        self.assertRaises(IOError, GitFile, foo, mode='a+bU')
+
+    def test_readonly(self):
+        f = GitFile(self.path('foo'), 'rb')
+        self.assertTrue(isinstance(f, file))
+        self.assertEquals('foo contents', f.read())
+        self.assertEquals('', f.read())
+        f.seek(4)
+        self.assertEquals('contents', f.read())
+        f.close()
+
+    def test_default_mode(self):
+        f = GitFile(self.path('foo'))
+        self.assertEquals('foo contents', f.read())
+        f.close()
+
+    def test_write(self):
+        foo = self.path('foo')
+        foo_lock = '%s.lock' % foo
+
+        orig_f = open(foo, 'rb')
+        self.assertEquals(orig_f.read(), 'foo contents')
+        orig_f.close()
+
+        self.assertFalse(os.path.exists(foo_lock))
+        f = GitFile(foo, 'wb')
+        self.assertFalse(f.closed)
+        self.assertRaises(AttributeError, getattr, f, 'not_a_file_property')
+
+        self.assertTrue(os.path.exists(foo_lock))
+        f.write('new stuff')
+        f.seek(4)
+        f.write('contents')
+        f.close()
+        self.assertFalse(os.path.exists(foo_lock))
+
+        new_f = open(foo, 'rb')
+        self.assertEquals('new contents', new_f.read())
+        new_f.close()
+
+    def test_open_twice(self):
+        foo = self.path('foo')
+        f1 = GitFile(foo, 'wb')
+        f1.write('new')
+        try:
+            f2 = GitFile(foo, 'wb')
+            self.fail()
+        except OSError, e:
+            self.assertEquals(errno.EEXIST, e.errno)
+        f1.write(' contents')
+        f1.close()
+
+        # Ensure trying to open twice doesn't affect original.
+        f = open(foo, 'rb')
+        self.assertEquals('new contents', f.read())
+        f.close()
+
+    def test_abort(self):
+        foo = self.path('foo')
+        foo_lock = '%s.lock' % foo
+
+        orig_f = open(foo, 'rb')
+        self.assertEquals(orig_f.read(), 'foo contents')
+        orig_f.close()
+
+        f = GitFile(foo, 'wb')
+        f.write('new contents')
+        f.abort()
+        self.assertTrue(f.closed)
+        self.assertFalse(os.path.exists(foo_lock))
+
+        new_orig_f = open(foo, 'rb')
+        self.assertEquals(new_orig_f.read(), 'foo contents')
+        new_orig_f.close()
+
+    def test_abort_close(self):
+        foo = self.path('foo')
+        f = GitFile(foo, 'wb')
+        f.abort()
+        try:
+            f.close()
+        except (IOError, OSError):
+            self.fail()
+
+        f = GitFile(foo, 'wb')
+        f.close()
+        try:
+            f.abort()
+        except (IOError, OSError):
+            self.fail()
+
+    def test_abort_close_removed(self):
+        foo = self.path('foo')
+        f = GitFile(foo, 'wb')
+
+        f._file.close()
+        os.remove(foo+".lock")
+
+        f.abort()
+        self.assertTrue(f._closed)

=== modified file 'dulwich/tests/test_index.py'
--- dulwich/tests/test_index.py	2009-06-16 14:56:53 +0000
+++ dulwich/tests/test_index.py	2010-06-10 10:46:37 +0000
@@ -1,22 +1,21 @@
 # test_index.py -- Tests for the git index
 # Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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
 # 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.
 
-
 """Tests for the index."""
 
 
@@ -24,9 +23,10 @@
     StringIO,
     )
 import os
+import shutil
 import stat
 import struct
-from unittest import TestCase
+import tempfile
 
 from dulwich.index import (
     Index,
@@ -42,6 +42,8 @@
 from dulwich.objects import (
     Blob,
     )
+from dulwich.tests import TestCase
+
 
 class IndexTestCase(TestCase):
 
@@ -51,7 +53,7 @@
         return Index(os.path.join(self.datadir, name))
 
 
-class SimpleIndexTestcase(IndexTestCase):
+class SimpleIndexTestCase(IndexTestCase):
 
     def test_len(self):
         self.assertEquals(1, len(self.get_simple_index("index")))
@@ -60,21 +62,38 @@
         self.assertEquals(['bla'], list(self.get_simple_index("index")))
 
     def test_getitem(self):
-        self.assertEquals( ((1230680220, 0), (1230680220, 0), 2050, 3761020, 33188, 1000, 1000, 0, 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391', 0)
-            , 
-                self.get_simple_index("index")["bla"])
+        self.assertEquals(((1230680220, 0), (1230680220, 0), 2050, 3761020,
+                           33188, 1000, 1000, 0,
+                           'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391', 0),
+                          self.get_simple_index("index")["bla"])
+
+    def test_empty(self):
+        i = self.get_simple_index("notanindex")
+        self.assertEquals(0, len(i))
+        self.assertFalse(os.path.exists(i._filename))
 
 
 class SimpleIndexWriterTestCase(IndexTestCase):
 
+    def setUp(self):
+        IndexTestCase.setUp(self)
+        self.tempdir = tempfile.mkdtemp()
+
+    def tearDown(self):
+        IndexTestCase.tearDown(self)
+        shutil.rmtree(self.tempdir)
+
     def test_simple_write(self):
-        entries = [('barbla', (1230680220, 0), (1230680220, 0), 2050, 3761020, 33188, 1000, 1000, 0, 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391', 0)]
-        x = open('test-simple-write-index', 'w+')
+        entries = [('barbla', (1230680220, 0), (1230680220, 0), 2050, 3761020,
+                    33188, 1000, 1000, 0,
+                    'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391', 0)]
+        filename = os.path.join(self.tempdir, 'test-simple-write-index')
+        x = open(filename, 'w+')
         try:
             write_index(x, entries)
         finally:
             x.close()
-        x = open('test-simple-write-index', 'r')
+        x = open(filename, 'r')
         try:
             self.assertEquals(entries, list(read_index(x)))
         finally:
@@ -108,7 +127,7 @@
         self.assertEquals(dirid, "c1a1deb9788150829579a8b4efa6311e7b638650")
         self.assertEquals((stat.S_IFDIR, dirid), self.store[rootid]["bla"])
         self.assertEquals((stat.S_IFREG, blob.id), self.store[dirid]["bar"])
-        self.assertEquals(set([rootid, dirid, blob.id]), 
+        self.assertEquals(set([rootid, dirid, blob.id]),
                           set(self.store._data.keys()))
 
 

=== modified file 'dulwich/tests/test_lru_cache.py'
--- dulwich/tests/test_lru_cache.py	2009-05-05 19:37:14 +0000
+++ dulwich/tests/test_lru_cache.py	2010-06-10 10:46:37 +0000
@@ -19,10 +19,12 @@
 from dulwich import (
     lru_cache,
     )
-import unittest
-
-
-class TestLRUCache(unittest.TestCase):
+from dulwich.tests import (
+    TestCase,
+    )
+
+
+class TestLRUCache(TestCase):
     """Test that LRU cache properly keeps track of entries."""
 
     def test_cache_size(self):
@@ -285,7 +287,7 @@
         self.assertEqual([6, 7, 8, 9, 10, 11], sorted(cache.keys()))
 
 
-class TestLRUSizeCache(unittest.TestCase):
+class TestLRUSizeCache(TestCase):
 
     def test_basic_init(self):
         cache = lru_cache.LRUSizeCache()

=== modified file 'dulwich/tests/test_object_store.py'
--- dulwich/tests/test_object_store.py	2009-05-27 08:15:45 +0000
+++ dulwich/tests/test_object_store.py	2011-01-14 18:33:07 +0000
@@ -1,52 +1,58 @@
 # test_object_store.py -- tests for object_store.py
 # Copyright (C) 2008 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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
 # 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.
 
-
 """Tests for the object store interface."""
 
 
-from unittest import TestCase
+import os
+import shutil
+import tempfile
 
+from dulwich.index import (
+    commit_tree,
+    )
+from dulwich.errors import (
+    NotTreeError,
+    )
 from dulwich.objects import (
+    object_class,
     Blob,
+    Tag,
+    Tree,
+    TreeEntry,
     )
 from dulwich.object_store import (
     DiskObjectStore,
     MemoryObjectStore,
-    )
-import os
-import shutil
-
-
-testobject = Blob()
-testobject.data = "yummy data"
-
-
-class SpecificDiskObjectStoreTests(TestCase):
-
-    def test_pack_dir(self):
-        o = DiskObjectStore("foo")
-        self.assertEquals(os.path.join("foo", "pack"), o.pack_dir)
-
-    def test_empty_packs(self):
-        o = DiskObjectStore("foo")
-        self.assertEquals([], o.packs)
-
+    tree_lookup_path,
+    )
+from dulwich.pack import (
+    write_pack_data,
+    )
+from dulwich.tests import (
+    TestCase,
+    )
+from dulwich.tests.utils import (
+    make_object,
+    )
+
+
+testobject = make_object(Blob, data="yummy data")
 
 
 class ObjectStoreTests(object):
@@ -55,10 +61,10 @@
         self.assertEquals([], list(self.store))
 
     def test_get_nonexistant(self):
-        self.assertRaises(KeyError, self.store.__getitem__, "a" * 40)
+        self.assertRaises(KeyError, lambda: self.store["a" * 40])
 
     def test_contains_nonexistant(self):
-        self.assertFalse(self.store.__contains__("a" * 40))
+        self.assertFalse(("a" * 40) in self.store)
 
     def test_add_objects_empty(self):
         self.store.add_objects([])
@@ -71,7 +77,7 @@
     def test_add_object(self):
         self.store.add_object(testobject)
         self.assertEquals(set([testobject.id]), set(self.store))
-        self.assertTrue(self.store.__contains__(testobject.id))
+        self.assertTrue(testobject.id in self.store)
         r = self.store[testobject.id]
         self.assertEquals(r, testobject)
 
@@ -79,23 +85,189 @@
         data = [(testobject, "mypath")]
         self.store.add_objects(data)
         self.assertEquals(set([testobject.id]), set(self.store))
-        self.assertTrue(self.store.__contains__(testobject.id))
+        self.assertTrue(testobject.id in self.store)
         r = self.store[testobject.id]
         self.assertEquals(r, testobject)
 
-
-class MemoryObjectStoreTests(ObjectStoreTests,TestCase):
-
-    def setUp(self):
-        TestCase.setUp(self)
-        self.store = MemoryObjectStore()
-
-
-class DiskObjectStoreTests(ObjectStoreTests,TestCase):
-
-    def setUp(self):
-        TestCase.setUp(self)
-        if os.path.exists("foo"):
-            shutil.rmtree("foo")
-        os.makedirs(os.path.join("foo", "pack"))
-        self.store = DiskObjectStore("foo")
+    def test_tree_changes(self):
+        blob_a1 = make_object(Blob, data='a1')
+        blob_a2 = make_object(Blob, data='a2')
+        blob_b = make_object(Blob, data='b')
+        for blob in [blob_a1, blob_a2, blob_b]:
+            self.store.add_object(blob)
+
+        blobs_1 = [('a', blob_a1.id, 0100644), ('b', blob_b.id, 0100644)]
+        tree1_id = commit_tree(self.store, blobs_1)
+        blobs_2 = [('a', blob_a2.id, 0100644), ('b', blob_b.id, 0100644)]
+        tree2_id = commit_tree(self.store, blobs_2)
+        change_a = (('a', 'a'), (0100644, 0100644), (blob_a1.id, blob_a2.id))
+        self.assertEquals([change_a],
+                          list(self.store.tree_changes(tree1_id, tree2_id)))
+        self.assertEquals(
+          [change_a, (('b', 'b'), (0100644, 0100644), (blob_b.id, blob_b.id))],
+          list(self.store.tree_changes(tree1_id, tree2_id,
+                                       want_unchanged=True)))
+
+    def test_iter_tree_contents(self):
+        blob_a = make_object(Blob, data='a')
+        blob_b = make_object(Blob, data='b')
+        blob_c = make_object(Blob, data='c')
+        for blob in [blob_a, blob_b, blob_c]:
+            self.store.add_object(blob)
+
+        blobs = [
+          ('a', blob_a.id, 0100644),
+          ('ad/b', blob_b.id, 0100644),
+          ('ad/bd/c', blob_c.id, 0100755),
+          ('ad/c', blob_c.id, 0100644),
+          ('c', blob_c.id, 0100644),
+          ]
+        tree_id = commit_tree(self.store, blobs)
+        self.assertEquals([TreeEntry(p, m, h) for (p, h, m) in blobs],
+                          list(self.store.iter_tree_contents(tree_id)))
+
+    def test_iter_tree_contents_include_trees(self):
+        blob_a = make_object(Blob, data='a')
+        blob_b = make_object(Blob, data='b')
+        blob_c = make_object(Blob, data='c')
+        for blob in [blob_a, blob_b, blob_c]:
+            self.store.add_object(blob)
+
+        blobs = [
+          ('a', blob_a.id, 0100644),
+          ('ad/b', blob_b.id, 0100644),
+          ('ad/bd/c', blob_c.id, 0100755),
+          ]
+        tree_id = commit_tree(self.store, blobs)
+        tree = self.store[tree_id]
+        tree_ad = self.store[tree['ad'][1]]
+        tree_bd = self.store[tree_ad['bd'][1]]
+
+        expected = [
+          TreeEntry('', 0040000, tree_id),
+          TreeEntry('a', 0100644, blob_a.id),
+          TreeEntry('ad', 0040000, tree_ad.id),
+          TreeEntry('ad/b', 0100644, blob_b.id),
+          TreeEntry('ad/bd', 0040000, tree_bd.id),
+          TreeEntry('ad/bd/c', 0100755, blob_c.id),
+          ]
+        actual = self.store.iter_tree_contents(tree_id, include_trees=True)
+        self.assertEquals(expected, list(actual))
+
+    def make_tag(self, name, obj):
+        tag = make_object(Tag, name=name, message='',
+                          tag_time=12345, tag_timezone=0,
+                          tagger='Test Tagger <test@xxxxxxxxxxx>',
+                          object=(object_class(obj.type_name), obj.id))
+        self.store.add_object(tag)
+        return tag
+
+    def test_peel_sha(self):
+        self.store.add_object(testobject)
+        tag1 = self.make_tag('1', testobject)
+        tag2 = self.make_tag('2', testobject)
+        tag3 = self.make_tag('3', testobject)
+        for obj in [testobject, tag1, tag2, tag3]:
+            self.assertEqual(testobject, self.store.peel_sha(obj.id))
+
+
+class MemoryObjectStoreTests(ObjectStoreTests, TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self.store = MemoryObjectStore()
+
+
+class PackBasedObjectStoreTests(ObjectStoreTests):
+
+    def tearDown(self):
+        for pack in self.store.packs:
+            pack.close()
+
+    def test_empty_packs(self):
+        self.assertEquals([], self.store.packs)
+
+    def test_pack_loose_objects(self):
+        b1 = make_object(Blob, data="yummy data")
+        self.store.add_object(b1)
+        b2 = make_object(Blob, data="more yummy data")
+        self.store.add_object(b2)
+        self.assertEquals([], self.store.packs)
+        self.assertEquals(2, self.store.pack_loose_objects())
+        self.assertNotEquals([], self.store.packs)
+        self.assertEquals(0, self.store.pack_loose_objects())
+
+
+class DiskObjectStoreTests(PackBasedObjectStoreTests, TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self.store_dir = tempfile.mkdtemp()
+        self.store = DiskObjectStore.init(self.store_dir)
+
+    def tearDown(self):
+        TestCase.tearDown(self)
+        PackBasedObjectStoreTests.tearDown(self)
+        shutil.rmtree(self.store_dir)
+
+    def test_pack_dir(self):
+        o = DiskObjectStore(self.store_dir)
+        self.assertEquals(os.path.join(self.store_dir, "pack"), o.pack_dir)
+
+    def test_add_pack(self):
+        o = DiskObjectStore(self.store_dir)
+        f, commit = o.add_pack()
+        b = make_object(Blob, data="more yummy data")
+        write_pack_data(f, [(b, None)], 1)
+        commit()
+
+    def test_add_thin_pack(self):
+        o = DiskObjectStore(self.store_dir)
+        f, commit = o.add_thin_pack()
+        b = make_object(Blob, data="more yummy data")
+        write_pack_data(f, [(b, None)], 1)
+        commit()
+
+
+class TreeLookupPathTests(TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self.store = MemoryObjectStore()
+        blob_a = make_object(Blob, data='a')
+        blob_b = make_object(Blob, data='b')
+        blob_c = make_object(Blob, data='c')
+        for blob in [blob_a, blob_b, blob_c]:
+            self.store.add_object(blob)
+
+        blobs = [
+          ('a', blob_a.id, 0100644),
+          ('ad/b', blob_b.id, 0100644),
+          ('ad/bd/c', blob_c.id, 0100755),
+          ('ad/c', blob_c.id, 0100644),
+          ('c', blob_c.id, 0100644),
+          ]
+        self.tree_id = commit_tree(self.store, blobs)
+
+    def get_object(self, sha):
+        return self.store[sha]
+
+    def test_lookup_blob(self):
+        o_id = tree_lookup_path(self.get_object, self.tree_id, 'a')[1]
+        self.assertTrue(isinstance(self.store[o_id], Blob))
+
+    def test_lookup_tree(self):
+        o_id = tree_lookup_path(self.get_object, self.tree_id, 'ad')[1]
+        self.assertTrue(isinstance(self.store[o_id], Tree))
+        o_id = tree_lookup_path(self.get_object, self.tree_id, 'ad/bd')[1]
+        self.assertTrue(isinstance(self.store[o_id], Tree))
+        o_id = tree_lookup_path(self.get_object, self.tree_id, 'ad/bd/')[1]
+        self.assertTrue(isinstance(self.store[o_id], Tree))
+
+    def test_lookup_nonexistent(self):
+        self.assertRaises(KeyError, tree_lookup_path, self.get_object, self.tree_id, 'j')
+
+    def test_lookup_not_tree(self):
+        self.assertRaises(NotTreeError, tree_lookup_path, self.get_object, self.tree_id, 'ad/b/j')
+
+# TODO: MissingObjectFinderTests

=== modified file 'dulwich/tests/test_objects.py'
--- dulwich/tests/test_objects.py	2009-07-08 21:33:45 +0000
+++ dulwich/tests/test_objects.py	2010-12-19 15:56:03 +0000
@@ -1,30 +1,38 @@
 # test_objects.py -- tests for objects.py
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
-# 
+#
 # 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 
+# 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.
 
-
 """Tests for git base objects."""
 
-
+# TODO: Round-trip parse-serialize-parse and serialize-parse-serialize tests.
+
+
+from cStringIO import StringIO
+import datetime
 import os
 import stat
-import unittest
 
+from dulwich.errors import (
+    ObjectFormatException,
+    )
+from dulwich._compat import (
+    permutations,
+    )
 from dulwich.objects import (
     Blob,
     Tree,
@@ -32,7 +40,25 @@
     Tag,
     format_timezone,
     hex_to_sha,
+    sha_to_hex,
+    hex_to_filename,
+    check_hexsha,
+    check_identity,
     parse_timezone,
+    TreeEntry,
+    parse_tree,
+    _parse_tree_py,
+    sorted_tree_items,
+    _sorted_tree_items_py,
+    )
+from dulwich.tests import (
+    TestCase,
+    )
+from utils import (
+    make_commit,
+    make_object,
+    functest_builder,
+    ext_functest_builder,
     )
 
 a_sha = '6f670c0fb53f9463760b7295fbb814e965fb20c8'
@@ -41,31 +67,41 @@
 tree_sha = '70c190eb48fa8bbb50ddc692a17b44cb781af7f6'
 tag_sha = '71033db03a03c6a36721efcf1968dd8f8e0cf023'
 
-class BlobReadTests(unittest.TestCase):
+
+class TestHexToSha(TestCase):
+
+    def test_simple(self):
+        self.assertEquals("\xab\xcd" * 10, hex_to_sha("abcd" * 10))
+
+    def test_reverse(self):
+        self.assertEquals("abcd" * 10, sha_to_hex("\xab\xcd" * 10))
+
+
+class BlobReadTests(TestCase):
     """Test decompression of blobs"""
-  
-    def get_sha_file(self, obj, base, sha):
-        return obj.from_file(os.path.join(os.path.dirname(__file__),
-                                          'data', base, sha))
-  
+
+    def get_sha_file(self, cls, base, sha):
+        dir = os.path.join(os.path.dirname(__file__), 'data', base)
+        return cls.from_path(hex_to_filename(dir, sha))
+
     def get_blob(self, sha):
         """Return the blob named sha from the test data dir"""
         return self.get_sha_file(Blob, 'blobs', sha)
-  
+
     def get_tree(self, sha):
         return self.get_sha_file(Tree, 'trees', sha)
-  
+
     def get_tag(self, sha):
         return self.get_sha_file(Tag, 'tags', sha)
-  
+
     def commit(self, sha):
         return self.get_sha_file(Commit, 'commits', sha)
-  
+
     def test_decompress_simple_blob(self):
         b = self.get_blob(a_sha)
         self.assertEqual(b.data, 'test 1\n')
         self.assertEqual(b.sha().hexdigest(), a_sha)
-  
+
     def test_hash(self):
         b = self.get_blob(a_sha)
         self.assertEqual(hash(b.id), hash(b))
@@ -76,29 +112,47 @@
         self.assertEqual(b.data, '')
         self.assertEqual(b.id, sha)
         self.assertEqual(b.sha().hexdigest(), sha)
-  
+
     def test_create_blob_from_string(self):
         string = 'test 2\n'
         b = Blob.from_string(string)
         self.assertEqual(b.data, string)
         self.assertEqual(b.sha().hexdigest(), b_sha)
-  
+
+    def test_legacy_from_file(self):
+        b1 = Blob.from_string("foo")
+        b_raw = b1.as_legacy_object()
+        b2 = b1.from_file(StringIO(b_raw))
+        self.assertEquals(b1, b2)
+
+    def test_chunks(self):
+        string = 'test 5\n'
+        b = Blob.from_string(string)
+        self.assertEqual([string], b.chunked)
+
+    def test_set_chunks(self):
+        b = Blob()
+        b.chunked = ['te', 'st', ' 5\n']
+        self.assertEqual('test 5\n', b.data)
+        b.chunked = ['te', 'st', ' 6\n']
+        self.assertEqual('test 6\n', b.as_raw_string())
+
     def test_parse_legacy_blob(self):
         string = 'test 3\n'
         b = self.get_blob(c_sha)
         self.assertEqual(b.data, string)
         self.assertEqual(b.sha().hexdigest(), c_sha)
-  
+
     def test_eq(self):
         blob1 = self.get_blob(a_sha)
         blob2 = self.get_blob(a_sha)
         self.assertEqual(blob1, blob2)
-  
+
     def test_read_tree_from_file(self):
         t = self.get_tree(tree_sha)
         self.assertEqual(t.entries()[0], (33188, 'a', a_sha))
         self.assertEqual(t.entries()[1], (33188, 'b', b_sha))
-  
+
     def test_read_tag_from_file(self):
         t = self.get_tag(tag_sha)
         self.assertEqual(t.object, (Commit, '51b668fd5bf7061b7d6fa525f88803e6cfadaa51'))
@@ -106,13 +160,13 @@
         self.assertEqual(t.tagger,'Ali Sabil <ali.sabil@xxxxxxxxx>')
         self.assertEqual(t.tag_time, 1231203091)
         self.assertEqual(t.message, 'This is a signed tag\n-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1.4.9 (GNU/Linux)\n\niEYEABECAAYFAkliqx8ACgkQqSMmLy9u/kcx5ACfakZ9NnPl02tOyYP6pkBoEkU1\n5EcAn0UFgokaSvS371Ym/4W9iJj6vh3h\n=ql7y\n-----END PGP SIGNATURE-----\n')
-  
-  
+
     def test_read_commit_from_file(self):
         sha = '60dacdc733de308bb77bb76ce0fb0f9b44c9769e'
         c = self.commit(sha)
         self.assertEqual(c.tree, tree_sha)
-        self.assertEqual(c.parents, ['0d89f20333fbb1d2f3a94da77f4981373d8f4310'])
+        self.assertEqual(c.parents,
+            ['0d89f20333fbb1d2f3a94da77f4981373d8f4310'])
         self.assertEqual(c.author,
             'James Westby <jw+debian@xxxxxxxxxxxxxxx>')
         self.assertEqual(c.committer,
@@ -121,7 +175,7 @@
         self.assertEqual(c.commit_timezone, 0)
         self.assertEqual(c.author_timezone, 0)
         self.assertEqual(c.message, 'Test commit\n')
-  
+
     def test_read_commit_no_parents(self):
         sha = '0d89f20333fbb1d2f3a94da77f4981373d8f4310'
         c = self.commit(sha)
@@ -135,7 +189,7 @@
         self.assertEqual(c.commit_timezone, 0)
         self.assertEqual(c.author_timezone, 0)
         self.assertEqual(c.message, 'Test commit\n')
-  
+
     def test_read_commit_two_parents(self):
         sha = '5dac377bdded4c9aeb8dff595f0faeebcc8498cc'
         c = self.commit(sha)
@@ -150,60 +204,205 @@
         self.assertEqual(c.commit_timezone, 0)
         self.assertEqual(c.author_timezone, 0)
         self.assertEqual(c.message, 'Merge ../b\n')
-  
-
-
-class CommitSerializationTests(unittest.TestCase):
-
-    def make_base(self):
-        c = Commit()
-        c.tree = 'd80c186a03f423a81b39df39dc87fd269736ca86'
-        c.parents = ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd', '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6']
-        c.author = 'James Westby <jw+debian@xxxxxxxxxxxxxxx>'
-        c.committer = 'James Westby <jw+debian@xxxxxxxxxxxxxxx>'
-        c.commit_time = 1174773719
-        c.author_time = 1174773719
-        c.commit_timezone = 0
-        c.author_timezone = 0
-        c.message =  'Merge ../b\n'
-        return c
+
+    def test_stub_sha(self):
+        sha = '5' * 40
+        c = make_commit(id=sha, message='foo')
+        self.assertTrue(isinstance(c, Commit))
+        self.assertEqual(sha, c.id)
+        self.assertNotEqual(sha, c._make_sha())
+
+
+class ShaFileCheckTests(TestCase):
+
+    def assertCheckFails(self, cls, data):
+        obj = cls()
+        def do_check():
+            obj.set_raw_string(data)
+            obj.check()
+        self.assertRaises(ObjectFormatException, do_check)
+
+    def assertCheckSucceeds(self, cls, data):
+        obj = cls()
+        obj.set_raw_string(data)
+        self.assertEqual(None, obj.check())
+
+
+class CommitSerializationTests(TestCase):
+
+    def make_commit(self, **kwargs):
+        attrs = {'tree': 'd80c186a03f423a81b39df39dc87fd269736ca86',
+                 'parents': ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd',
+                             '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6'],
+                 'author': 'James Westby <jw+debian@xxxxxxxxxxxxxxx>',
+                 'committer': 'James Westby <jw+debian@xxxxxxxxxxxxxxx>',
+                 'commit_time': 1174773719,
+                 'author_time': 1174773719,
+                 'commit_timezone': 0,
+                 'author_timezone': 0,
+                 'message':  'Merge ../b\n'}
+        attrs.update(kwargs)
+        return make_commit(**attrs)
 
     def test_encoding(self):
-        c = self.make_base()
-        c.encoding = "iso8859-1"
-        self.assertTrue("encoding iso8859-1\n" in c.as_raw_string())        
+        c = self.make_commit(encoding='iso8859-1')
+        self.assertTrue('encoding iso8859-1\n' in c.as_raw_string())
 
     def test_short_timestamp(self):
-        c = self.make_base()
-        c.commit_time = 30
+        c = self.make_commit(commit_time=30)
         c1 = Commit()
         c1.set_raw_string(c.as_raw_string())
         self.assertEquals(30, c1.commit_time)
 
+    def test_raw_length(self):
+        c = self.make_commit()
+        self.assertEquals(len(c.as_raw_string()), c.raw_length())
+
     def test_simple(self):
-        c = self.make_base()
+        c = self.make_commit()
         self.assertEquals(c.id, '5dac377bdded4c9aeb8dff595f0faeebcc8498cc')
         self.assertEquals(
                 'tree d80c186a03f423a81b39df39dc87fd269736ca86\n'
                 'parent ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd\n'
                 'parent 4cffe90e0a41ad3f5190079d7c8f036bde29cbe6\n'
-                'author James Westby <jw+debian@xxxxxxxxxxxxxxx> 1174773719 +0000\n'
-                'committer James Westby <jw+debian@xxxxxxxxxxxxxxx> 1174773719 +0000\n'
+                'author James Westby <jw+debian@xxxxxxxxxxxxxxx> '
+                '1174773719 +0000\n'
+                'committer James Westby <jw+debian@xxxxxxxxxxxxxxx> '
+                '1174773719 +0000\n'
                 '\n'
                 'Merge ../b\n', c.as_raw_string())
 
     def test_timezone(self):
-        c = self.make_base()
-        c.commit_timezone = 5 * 60
+        c = self.make_commit(commit_timezone=(5 * 60))
         self.assertTrue(" +0005\n" in c.as_raw_string())
 
     def test_neg_timezone(self):
-        c = self.make_base()
-        c.commit_timezone = -1 * 3600
+        c = self.make_commit(commit_timezone=(-1 * 3600))
         self.assertTrue(" -0100\n" in c.as_raw_string())
 
 
-class TreeSerializationTests(unittest.TestCase):
+default_committer = 'James Westby <jw+debian@xxxxxxxxxxxxxxx> 1174773719 +0000'
+
+class CommitParseTests(ShaFileCheckTests):
+
+    def make_commit_lines(self,
+                          tree='d80c186a03f423a81b39df39dc87fd269736ca86',
+                          parents=['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd',
+                                   '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6'],
+                          author=default_committer,
+                          committer=default_committer,
+                          encoding=None,
+                          message='Merge ../b\n',
+                          extra=None):
+        lines = []
+        if tree is not None:
+            lines.append('tree %s' % tree)
+        if parents is not None:
+            lines.extend('parent %s' % p for p in parents)
+        if author is not None:
+            lines.append('author %s' % author)
+        if committer is not None:
+            lines.append('committer %s' % committer)
+        if encoding is not None:
+            lines.append('encoding %s' % encoding)
+        if extra is not None:
+            for name, value in sorted(extra.iteritems()):
+                lines.append('%s %s' % (name, value))
+        lines.append('')
+        if message is not None:
+            lines.append(message)
+        return lines
+
+    def make_commit_text(self, **kwargs):
+        return '\n'.join(self.make_commit_lines(**kwargs))
+
+    def test_simple(self):
+        c = Commit.from_string(self.make_commit_text())
+        self.assertEquals('Merge ../b\n', c.message)
+        self.assertEquals('James Westby <jw+debian@xxxxxxxxxxxxxxx>', c.author)
+        self.assertEquals('James Westby <jw+debian@xxxxxxxxxxxxxxx>',
+                          c.committer)
+        self.assertEquals('d80c186a03f423a81b39df39dc87fd269736ca86', c.tree)
+        self.assertEquals(['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd',
+                           '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6'],
+                          c.parents)
+        expected_time = datetime.datetime(2007, 3, 24, 22, 1, 59)
+        self.assertEquals(expected_time,
+                          datetime.datetime.utcfromtimestamp(c.commit_time))
+        self.assertEquals(0, c.commit_timezone)
+        self.assertEquals(expected_time,
+                          datetime.datetime.utcfromtimestamp(c.author_time))
+        self.assertEquals(0, c.author_timezone)
+        self.assertEquals(None, c.encoding)
+
+    def test_custom(self):
+        c = Commit.from_string(self.make_commit_text(
+          extra={'extra-field': 'data'}))
+        self.assertEquals([('extra-field', 'data')], c.extra)
+
+    def test_encoding(self):
+        c = Commit.from_string(self.make_commit_text(encoding='UTF-8'))
+        self.assertEquals('UTF-8', c.encoding)
+
+    def test_check(self):
+        self.assertCheckSucceeds(Commit, self.make_commit_text())
+        self.assertCheckSucceeds(Commit, self.make_commit_text(parents=None))
+        self.assertCheckSucceeds(Commit,
+                                 self.make_commit_text(encoding='UTF-8'))
+
+        self.assertCheckFails(Commit, self.make_commit_text(tree='xxx'))
+        self.assertCheckFails(Commit, self.make_commit_text(
+          parents=[a_sha, 'xxx']))
+        bad_committer = "some guy without an email address 1174773719 +0000"
+        self.assertCheckFails(Commit,
+                              self.make_commit_text(committer=bad_committer))
+        self.assertCheckFails(Commit,
+                              self.make_commit_text(author=bad_committer))
+        self.assertCheckFails(Commit, self.make_commit_text(author=None))
+        self.assertCheckFails(Commit, self.make_commit_text(committer=None))
+        self.assertCheckFails(Commit, self.make_commit_text(
+          author=None, committer=None))
+
+    def test_check_duplicates(self):
+        # duplicate each of the header fields
+        for i in xrange(5):
+            lines = self.make_commit_lines(parents=[a_sha], encoding='UTF-8')
+            lines.insert(i, lines[i])
+            text = '\n'.join(lines)
+            if lines[i].startswith('parent'):
+                # duplicate parents are ok for now
+                self.assertCheckSucceeds(Commit, text)
+            else:
+                self.assertCheckFails(Commit, text)
+
+    def test_check_order(self):
+        lines = self.make_commit_lines(parents=[a_sha], encoding='UTF-8')
+        headers = lines[:5]
+        rest = lines[5:]
+        # of all possible permutations, ensure only the original succeeds
+        for perm in permutations(headers):
+            perm = list(perm)
+            text = '\n'.join(perm + rest)
+            if perm == headers:
+                self.assertCheckSucceeds(Commit, text)
+            else:
+                self.assertCheckFails(Commit, text)
+
+
+_TREE_ITEMS = {
+  'a.c': (0100755, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+  'a': (stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+  'a/c': (stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+  }
+
+_SORTED_TREE_ITEMS = [
+  TreeEntry('a.c', 0100755, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+  TreeEntry('a', stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+  TreeEntry('a/c', stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+  ]
+
+
+class TreeTests(ShaFileCheckTests):
 
     def test_simple(self):
         myhexsha = "d80c186a03f423a81b39df39dc87fd269736ca86"
@@ -212,42 +411,145 @@
         self.assertEquals('100755 myname\0' + hex_to_sha(myhexsha),
                 x.as_raw_string())
 
-    def test_tree_dir_sort(self):
+    def test_tree_update_id(self):
         x = Tree()
         x["a.c"] = (0100755, "d80c186a03f423a81b39df39dc87fd269736ca86")
-        x["a"] = (stat.S_IFDIR, "d80c186a03f423a81b39df39dc87fd269736ca86")
-        x["a/c"] = (stat.S_IFDIR, "d80c186a03f423a81b39df39dc87fd269736ca86")
-        self.assertEquals(["a.c", "a", "a/c"], [p[0] for p in x.iteritems()])
-
-
-class TagSerializeTests(unittest.TestCase):
+        self.assertEquals("0c5c6bc2c081accfbc250331b19e43b904ab9cdd", x.id)
+        x["a.b"] = (stat.S_IFDIR, "d80c186a03f423a81b39df39dc87fd269736ca86")
+        self.assertEquals("07bfcb5f3ada15bbebdfa3bbb8fd858a363925c8", x.id)
+
+    def test_tree_iteritems_dir_sort(self):
+        x = Tree()
+        for name, item in _TREE_ITEMS.iteritems():
+            x[name] = item
+        self.assertEquals(_SORTED_TREE_ITEMS, list(x.iteritems()))
+
+    def test_tree_items_dir_sort(self):
+        x = Tree()
+        for name, item in _TREE_ITEMS.iteritems():
+            x[name] = item
+        self.assertEquals(_SORTED_TREE_ITEMS, x.items())
+
+    def _do_test_parse_tree(self, parse_tree):
+        dir = os.path.join(os.path.dirname(__file__), 'data', 'trees')
+        o = Tree.from_path(hex_to_filename(dir, tree_sha))
+        self.assertEquals([('a', 0100644, a_sha), ('b', 0100644, b_sha)],
+                          list(parse_tree(o.as_raw_string())))
+        # test a broken tree that has a leading 0 on the file mode
+        broken_tree = '0100644 foo\0' + hex_to_sha(a_sha)
+
+        def eval_parse_tree(*args, **kwargs):
+            return list(parse_tree(*args, **kwargs))
+
+        self.assertEquals([('foo', 0100644, a_sha)],
+                          eval_parse_tree(broken_tree))
+        self.assertRaises(ObjectFormatException,
+                          eval_parse_tree, broken_tree, strict=True)
+
+    test_parse_tree = functest_builder(_do_test_parse_tree, _parse_tree_py)
+    test_parse_tree_extension = ext_functest_builder(_do_test_parse_tree,
+                                                     parse_tree)
+
+    def _do_test_sorted_tree_items(self, sorted_tree_items):
+        def do_sort(entries):
+            return list(sorted_tree_items(entries, False))
+
+        actual = do_sort(_TREE_ITEMS)
+        self.assertEqual(_SORTED_TREE_ITEMS, actual)
+        self.assertTrue(isinstance(actual[0], TreeEntry))
+
+        # C/Python implementations may differ in specific error types, but
+        # should all error on invalid inputs.
+        # For example, the C implementation has stricter type checks, so may
+        # raise TypeError where the Python implementation raises AttributeError.
+        errors = (TypeError, ValueError, AttributeError)
+        self.assertRaises(errors, do_sort, 'foo')
+        self.assertRaises(errors, do_sort, {'foo': (1, 2, 3)})
+
+        myhexsha = 'd80c186a03f423a81b39df39dc87fd269736ca86'
+        self.assertRaises(errors, do_sort, {'foo': ('xxx', myhexsha)})
+        self.assertRaises(errors, do_sort, {'foo': (0100755, 12345)})
+
+    test_sorted_tree_items = functest_builder(_do_test_sorted_tree_items,
+                                              _sorted_tree_items_py)
+    test_sorted_tree_items_extension = ext_functest_builder(
+      _do_test_sorted_tree_items, sorted_tree_items)
+
+    def _do_test_sorted_tree_items_name_order(self, sorted_tree_items):
+        self.assertEqual([
+          TreeEntry('a', stat.S_IFDIR,
+                    'd80c186a03f423a81b39df39dc87fd269736ca86'),
+          TreeEntry('a.c', 0100755, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+          TreeEntry('a/c', stat.S_IFDIR,
+                    'd80c186a03f423a81b39df39dc87fd269736ca86'),
+          ], list(sorted_tree_items(_TREE_ITEMS, True)))
+
+    test_sorted_tree_items_name_order = functest_builder(
+      _do_test_sorted_tree_items_name_order, _sorted_tree_items_py)
+    test_sorted_tree_items_name_order_extension = ext_functest_builder(
+      _do_test_sorted_tree_items_name_order, sorted_tree_items)
+
+    def test_check(self):
+        t = Tree
+        sha = hex_to_sha(a_sha)
+
+        # filenames
+        self.assertCheckSucceeds(t, '100644 .a\0%s' % sha)
+        self.assertCheckFails(t, '100644 \0%s' % sha)
+        self.assertCheckFails(t, '100644 .\0%s' % sha)
+        self.assertCheckFails(t, '100644 a/a\0%s' % sha)
+        self.assertCheckFails(t, '100644 ..\0%s' % sha)
+
+        # modes
+        self.assertCheckSucceeds(t, '100644 a\0%s' % sha)
+        self.assertCheckSucceeds(t, '100755 a\0%s' % sha)
+        self.assertCheckSucceeds(t, '160000 a\0%s' % sha)
+        # TODO more whitelisted modes
+        self.assertCheckFails(t, '123456 a\0%s' % sha)
+        self.assertCheckFails(t, '123abc a\0%s' % sha)
+        # should fail check, but parses ok
+        self.assertCheckFails(t, '0100644 foo\0' + sha)
+
+        # shas
+        self.assertCheckFails(t, '100644 a\0%s' % ('x' * 5))
+        self.assertCheckFails(t, '100644 a\0%s' % ('x' * 18 + '\0'))
+        self.assertCheckFails(t, '100644 a\0%s\n100644 b\0%s' % ('x' * 21, sha))
+
+        # ordering
+        sha2 = hex_to_sha(b_sha)
+        self.assertCheckSucceeds(t, '100644 a\0%s\n100644 b\0%s' % (sha, sha))
+        self.assertCheckSucceeds(t, '100644 a\0%s\n100644 b\0%s' % (sha, sha2))
+        self.assertCheckFails(t, '100644 a\0%s\n100755 a\0%s' % (sha, sha2))
+        self.assertCheckFails(t, '100644 b\0%s\n100644 a\0%s' % (sha2, sha))
+
+    def test_iter(self):
+        t = Tree()
+        t["foo"] = (0100644, a_sha)
+        self.assertEquals(set(["foo"]), set(t))
+
+
+class TagSerializeTests(TestCase):
 
     def test_serialize_simple(self):
-        x = Tag()
-        x.tagger = "Jelmer Vernooij <jelmer@xxxxxxxxx>"
-        x.name = "0.1"
-        x.message = "Tag 0.1"
-        x.object = (3, "d80c186a03f423a81b39df39dc87fd269736ca86")
-        x.tag_time = 423423423
-        x.tag_timezone = 0
-        self.assertEquals("""object d80c186a03f423a81b39df39dc87fd269736ca86
-type blob
-tag 0.1
-tagger Jelmer Vernooij <jelmer@xxxxxxxxx> 423423423 +0000
-
-Tag 0.1""", x.as_raw_string())
-
-
-class TagParseTests(unittest.TestCase):
-
-    def test_parse_ctime(self):
-        x = Tag()
-        x.set_raw_string("""object a38d6181ff27824c79fc7df825164a212eff6a3f
-type commit
-tag v2.6.22-rc7
-tagger Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxxxxxxxx> Sun Jul 1 12:54:34 2007 -0700
-
-Linux 2.6.22-rc7
+        x = make_object(Tag,
+                        tagger='Jelmer Vernooij <jelmer@xxxxxxxxx>',
+                        name='0.1',
+                        message='Tag 0.1',
+                        object=(Blob, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+                        tag_time=423423423,
+                        tag_timezone=0)
+        self.assertEquals(('object d80c186a03f423a81b39df39dc87fd269736ca86\n'
+                           'type blob\n'
+                           'tag 0.1\n'
+                           'tagger Jelmer Vernooij <jelmer@xxxxxxxxx> '
+                           '423423423 +0000\n'
+                           '\n'
+                           'Tag 0.1'), x.as_raw_string())
+
+
+default_tagger = ('Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxxxxxxxx> '
+                  '1183319674 -0700')
+default_message = """Linux 2.6.22-rc7
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.7 (GNU/Linux)
 
@@ -255,39 +557,136 @@
 OK2XeQOiEeXtT76rV4t2WR4=
 =ivrA
 -----END PGP SIGNATURE-----
-""")
-        self.assertEquals("Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxxxxxxxx>", x.tagger)
+"""
+
+
+class TagParseTests(ShaFileCheckTests):
+    def make_tag_lines(self,
+                       object_sha="a38d6181ff27824c79fc7df825164a212eff6a3f",
+                       object_type_name="commit",
+                       name="v2.6.22-rc7",
+                       tagger=default_tagger,
+                       message=default_message):
+        lines = []
+        if object_sha is not None:
+            lines.append("object %s" % object_sha)
+        if object_type_name is not None:
+            lines.append("type %s" % object_type_name)
+        if name is not None:
+            lines.append("tag %s" % name)
+        if tagger is not None:
+            lines.append("tagger %s" % tagger)
+        lines.append("")
+        if message is not None:
+            lines.append(message)
+        return lines
+
+    def make_tag_text(self, **kwargs):
+        return "\n".join(self.make_tag_lines(**kwargs))
+
+    def test_parse(self):
+        x = Tag()
+        x.set_raw_string(self.make_tag_text())
+        self.assertEquals(
+            "Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxxxxxxxx>", x.tagger)
         self.assertEquals("v2.6.22-rc7", x.name)
+        object_type, object_sha = x.object
+        self.assertEquals("a38d6181ff27824c79fc7df825164a212eff6a3f",
+                          object_sha)
+        self.assertEquals(Commit, object_type)
+        self.assertEquals(datetime.datetime.utcfromtimestamp(x.tag_time),
+                          datetime.datetime(2007, 7, 1, 19, 54, 34))
+        self.assertEquals(-25200, x.tag_timezone)
 
     def test_parse_no_tagger(self):
         x = Tag()
-        x.set_raw_string("""object a38d6181ff27824c79fc7df825164a212eff6a3f
-type commit
-tag v2.6.22-rc7
-
-Linux 2.6.22-rc7
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.7 (GNU/Linux)
-
-iD8DBQBGiAaAF3YsRnbiHLsRAitMAKCiLboJkQECM/jpYsY3WPfvUgLXkACgg3ql
-OK2XeQOiEeXtT76rV4t2WR4=
-=ivrA
------END PGP SIGNATURE-----
-""")
+        x.set_raw_string(self.make_tag_text(tagger=None))
         self.assertEquals(None, x.tagger)
         self.assertEquals("v2.6.22-rc7", x.name)
 
-
-class TimezoneTests(unittest.TestCase):
+    def test_check(self):
+        self.assertCheckSucceeds(Tag, self.make_tag_text())
+        self.assertCheckFails(Tag, self.make_tag_text(object_sha=None))
+        self.assertCheckFails(Tag, self.make_tag_text(object_type_name=None))
+        self.assertCheckFails(Tag, self.make_tag_text(name=None))
+        self.assertCheckFails(Tag, self.make_tag_text(name=''))
+        self.assertCheckFails(Tag, self.make_tag_text(
+          object_type_name="foobar"))
+        self.assertCheckFails(Tag, self.make_tag_text(
+          tagger="some guy without an email address 1183319674 -0700"))
+        self.assertCheckFails(Tag, self.make_tag_text(
+          tagger=("Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxxxxxxxx> "
+                  "Sun 7 Jul 2007 12:54:34 +0700")))
+        self.assertCheckFails(Tag, self.make_tag_text(object_sha="xxx"))
+
+    def test_check_duplicates(self):
+        # duplicate each of the header fields
+        for i in xrange(4):
+            lines = self.make_tag_lines()
+            lines.insert(i, lines[i])
+            self.assertCheckFails(Tag, '\n'.join(lines))
+
+    def test_check_order(self):
+        lines = self.make_tag_lines()
+        headers = lines[:4]
+        rest = lines[4:]
+        # of all possible permutations, ensure only the original succeeds
+        for perm in permutations(headers):
+            perm = list(perm)
+            text = '\n'.join(perm + rest)
+            if perm == headers:
+                self.assertCheckSucceeds(Tag, text)
+            else:
+                self.assertCheckFails(Tag, text)
+
+
+class CheckTests(TestCase):
+
+    def test_check_hexsha(self):
+        check_hexsha(a_sha, "failed to check good sha")
+        self.assertRaises(ObjectFormatException, check_hexsha, '1' * 39,
+                          'sha too short')
+        self.assertRaises(ObjectFormatException, check_hexsha, '1' * 41,
+                          'sha too long')
+        self.assertRaises(ObjectFormatException, check_hexsha, 'x' * 40,
+                          'invalid characters')
+
+    def test_check_identity(self):
+        check_identity("Dave Borowitz <dborowitz@xxxxxxxxxx>",
+                       "failed to check good identity")
+        check_identity("<dborowitz@xxxxxxxxxx>",
+                       "failed to check good identity")
+        self.assertRaises(ObjectFormatException, check_identity,
+                          "Dave Borowitz", "no email")
+        self.assertRaises(ObjectFormatException, check_identity,
+                          "Dave Borowitz <dborowitz", "incomplete email")
+        self.assertRaises(ObjectFormatException, check_identity,
+                          "dborowitz@xxxxxxxxxx>", "incomplete email")
+        self.assertRaises(ObjectFormatException, check_identity,
+                          "Dave Borowitz <<dborowitz@xxxxxxxxxx>", "typo")
+        self.assertRaises(ObjectFormatException, check_identity,
+                          "Dave Borowitz <dborowitz@xxxxxxxxxx>>", "typo")
+        self.assertRaises(ObjectFormatException, check_identity,
+                          "Dave Borowitz <dborowitz@xxxxxxxxxx>xxx",
+                          "trailing characters")
+
+
+class TimezoneTests(TestCase):
 
     def test_parse_timezone_utc(self):
-        self.assertEquals(0, parse_timezone("+0000"))
+        self.assertEquals((0, False), parse_timezone("+0000"))
+
+    def test_parse_timezone_utc_negative(self):
+        self.assertEquals((0, True), parse_timezone("-0000"))
 
     def test_generate_timezone_utc(self):
         self.assertEquals("+0000", format_timezone(0))
 
+    def test_generate_timezone_utc_negative(self):
+        self.assertEquals("-0000", format_timezone(0, True))
+
     def test_parse_timezone_cet(self):
-        self.assertEquals(60 * 60, parse_timezone("+0100"))
+        self.assertEquals((60 * 60, False), parse_timezone("+0100"))
 
     def test_format_timezone_cet(self):
         self.assertEquals("+0100", format_timezone(60 * 60))
@@ -296,10 +695,12 @@
         self.assertEquals("-0400", format_timezone(-4 * 60 * 60))
 
     def test_parse_timezone_pdt(self):
-        self.assertEquals(-4 * 60 * 60, parse_timezone("-0400"))
+        self.assertEquals((-4 * 60 * 60, False), parse_timezone("-0400"))
 
     def test_format_timezone_pdt_half(self):
-        self.assertEquals("-0440", format_timezone(int(((-4 * 60) - 40) * 60)))
+        self.assertEquals("-0440",
+            format_timezone(int(((-4 * 60) - 40) * 60)))
 
     def test_parse_timezone_pdt_half(self):
-        self.assertEquals(((-4 * 60) - 40) * 60, parse_timezone("-0440"))
+        self.assertEquals((((-4 * 60) - 40) * 60, False),
+            parse_timezone("-0440"))

=== modified file 'dulwich/tests/test_pack.py'
--- dulwich/tests/test_pack.py	2009-05-19 19:09:14 +0000
+++ dulwich/tests/test_pack.py	2010-12-21 09:41:55 +0000
@@ -1,45 +1,59 @@
 # test_pack.py -- Tests for the handling of git packs.
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
 # Copyright (C) 2008 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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.
 
-
 """Tests for Dulwich packs."""
 
 
+from cStringIO import StringIO
 import os
-import unittest
+import shutil
+import tempfile
+import zlib
 
+from dulwich.errors import (
+    ChecksumMismatch,
+    )
+from dulwich.file import (
+    GitFile,
+    )
 from dulwich.objects import (
+    hex_to_sha,
+    sha_to_hex,
     Tree,
     )
 from dulwich.pack import (
+    MemoryPackIndex,
     Pack,
     PackData,
+    ThinPackData,
     apply_delta,
     create_delta,
     load_pack_index,
-    hex_to_sha,
-    read_zlib,
-    sha_to_hex,
+    read_zlib_chunks,
+    write_pack_header,
     write_pack_index_v1,
     write_pack_index_v2,
     write_pack,
     )
+from dulwich.tests import (
+    TestCase,
+    )
 
 pack1_sha = 'bc63ddad95e7321ee734ea11a7a62d314e0d7481'
 
@@ -47,26 +61,42 @@
 tree_sha = 'b2a2766a2879c209ab1176e7e778b81ae422eeaa'
 commit_sha = 'f18faa16531ac570a3fdc8c7ca16682548dafd12'
 
-class PackTests(unittest.TestCase):
+
+class PackTests(TestCase):
     """Base class for testing packs"""
-  
-    datadir = os.path.join(os.path.dirname(__file__), 'data/packs')
-  
+
+    def setUp(self):
+        super(PackTests, self).setUp()
+        self.tempdir = tempfile.mkdtemp()
+
+    def tearDown(self):
+        shutil.rmtree(self.tempdir)
+        super(PackTests, self).tearDown()
+
+    datadir = os.path.abspath(os.path.join(os.path.dirname(__file__),
+        'data/packs'))
+
     def get_pack_index(self, sha):
         """Returns a PackIndex from the datadir with the given sha"""
         return load_pack_index(os.path.join(self.datadir, 'pack-%s.idx' % sha))
-  
+
     def get_pack_data(self, sha):
         """Returns a PackData object from the datadir with the given sha"""
         return PackData(os.path.join(self.datadir, 'pack-%s.pack' % sha))
-  
+
     def get_pack(self, sha):
         return Pack(os.path.join(self.datadir, 'pack-%s' % sha))
 
+    def assertSucceeds(self, func, *args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except ChecksumMismatch, e:
+            self.fail(e)
+
 
 class PackIndexTests(PackTests):
     """Class that tests the index of packfiles"""
-  
+
     def test_object_index(self):
         """Tests that the correct object offset is returned from the index."""
         p = self.get_pack_index(pack1_sha)
@@ -74,88 +104,137 @@
         self.assertEqual(p.object_index(a_sha), 178)
         self.assertEqual(p.object_index(tree_sha), 138)
         self.assertEqual(p.object_index(commit_sha), 12)
-  
+
     def test_index_len(self):
         p = self.get_pack_index(pack1_sha)
         self.assertEquals(3, len(p))
-  
+
     def test_get_stored_checksum(self):
         p = self.get_pack_index(pack1_sha)
-        self.assertEquals("\xf2\x84\x8e*\xd1o2\x9a\xe1\xc9.;\x95\xe9\x18\x88\xda\xa5\xbd\x01", str(p.get_stored_checksum()))
-        self.assertEquals( 'r\x19\x80\xe8f\xaf\x9a_\x93\xadgAD\xe1E\x9b\x8b\xa3\xe7\xb7' , str(p.get_pack_checksum()))
-  
+        self.assertEquals('f2848e2ad16f329ae1c92e3b95e91888daa5bd01',
+                          sha_to_hex(p.get_stored_checksum()))
+        self.assertEquals('721980e866af9a5f93ad674144e1459b8ba3e7b7',
+                          sha_to_hex(p.get_pack_checksum()))
+
     def test_index_check(self):
         p = self.get_pack_index(pack1_sha)
-        self.assertEquals(True, p.check())
-  
+        self.assertSucceeds(p.check)
+
     def test_iterentries(self):
         p = self.get_pack_index(pack1_sha)
-        self.assertEquals([('og\x0c\x0f\xb5?\x94cv\x0br\x95\xfb\xb8\x14\xe9e\xfb \xc8', 178, None), ('\xb2\xa2vj(y\xc2\t\xab\x11v\xe7\xe7x\xb8\x1a\xe4"\xee\xaa', 138, None), ('\xf1\x8f\xaa\x16S\x1a\xc5p\xa3\xfd\xc8\xc7\xca\x16h%H\xda\xfd\x12', 12, None)], list(p.iterentries()))
-  
+        entries = [(sha_to_hex(s), o, c) for s, o, c in p.iterentries()]
+        self.assertEquals([
+          ('6f670c0fb53f9463760b7295fbb814e965fb20c8', 178, None),
+          ('b2a2766a2879c209ab1176e7e778b81ae422eeaa', 138, None),
+          ('f18faa16531ac570a3fdc8c7ca16682548dafd12', 12, None)
+          ], entries)
+
     def test_iter(self):
         p = self.get_pack_index(pack1_sha)
         self.assertEquals(set([tree_sha, commit_sha, a_sha]), set(p))
-  
-
-class TestPackDeltas(unittest.TestCase):
-  
-    test_string1 = "The answer was flailing in the wind"
-    test_string2 = "The answer was falling down the pipe"
-    test_string3 = "zzzzz"
-  
-    test_string_empty = ""
-    test_string_big = "Z" * 8192
-  
+
+
+class TestPackDeltas(TestCase):
+
+    test_string1 = 'The answer was flailing in the wind'
+    test_string2 = 'The answer was falling down the pipe'
+    test_string3 = 'zzzzz'
+
+    test_string_empty = ''
+    test_string_big = 'Z' * 8192
+
     def _test_roundtrip(self, base, target):
         self.assertEquals(target,
-            apply_delta(base, create_delta(base, target)))
-  
+                          ''.join(apply_delta(base, create_delta(base, target))))
+
     def test_nochange(self):
         self._test_roundtrip(self.test_string1, self.test_string1)
-  
+
     def test_change(self):
         self._test_roundtrip(self.test_string1, self.test_string2)
-  
+
     def test_rewrite(self):
         self._test_roundtrip(self.test_string1, self.test_string3)
-  
+
     def test_overflow(self):
         self._test_roundtrip(self.test_string_empty, self.test_string_big)
 
 
 class TestPackData(PackTests):
     """Tests getting the data from the packfile."""
-  
+
     def test_create_pack(self):
         p = self.get_pack_data(pack1_sha)
-  
+
+    def test_from_file(self):
+        path = os.path.join(self.datadir, 'pack-%s.pack' % pack1_sha)
+        PackData.from_file(open(path), os.path.getsize(path))
+
+    # TODO: more ThinPackData tests.
+    def test_thin_from_file(self):
+        test_sha = '1' * 40
+
+        def resolve(sha):
+            self.assertEqual(test_sha, sha)
+            return 3, 'data'
+
+        path = os.path.join(self.datadir, 'pack-%s.pack' % pack1_sha)
+        data = ThinPackData.from_file(resolve, open(path),
+                                      os.path.getsize(path))
+        idx = self.get_pack_index(pack1_sha)
+        Pack.from_objects(data, idx)
+        self.assertEqual((None, 3, 'data'), data.get_ref(test_sha))
+
     def test_pack_len(self):
         p = self.get_pack_data(pack1_sha)
         self.assertEquals(3, len(p))
-  
+
     def test_index_check(self):
         p = self.get_pack_data(pack1_sha)
-        self.assertEquals(True, p.check())
-  
+        self.assertSucceeds(p.check)
+
     def test_iterobjects(self):
         p = self.get_pack_data(pack1_sha)
-        self.assertEquals([(12, 1, 'tree b2a2766a2879c209ab1176e7e778b81ae422eeaa\nauthor James Westby <jw+debian@xxxxxxxxxxxxxxx> 1174945067 +0100\ncommitter James Westby <jw+debian@xxxxxxxxxxxxxxx> 1174945067 +0100\n\nTest commit\n', 3775879613L), (138, 2, '100644 a\x00og\x0c\x0f\xb5?\x94cv\x0br\x95\xfb\xb8\x14\xe9e\xfb \xc8', 912998690L), (178, 3, 'test 1\n', 1373561701L)], list(p.iterobjects()))
-  
+        commit_data = ('tree b2a2766a2879c209ab1176e7e778b81ae422eeaa\n'
+                       'author James Westby <jw+debian@xxxxxxxxxxxxxxx> '
+                       '1174945067 +0100\n'
+                       'committer James Westby <jw+debian@xxxxxxxxxxxxxxx> '
+                       '1174945067 +0100\n'
+                       '\n'
+                       'Test commit\n')
+        blob_sha = '6f670c0fb53f9463760b7295fbb814e965fb20c8'
+        tree_data = '100644 a\0%s' % hex_to_sha(blob_sha)
+        actual = []
+        for offset, type_num, chunks, crc32 in p.iterobjects():
+            actual.append((offset, type_num, ''.join(chunks), crc32))
+        self.assertEquals([
+          (12, 1, commit_data, 3775879613L),
+          (138, 2, tree_data, 912998690L),
+          (178, 3, 'test 1\n', 1373561701L)
+          ], actual)
+
     def test_iterentries(self):
         p = self.get_pack_data(pack1_sha)
-        self.assertEquals(set([('og\x0c\x0f\xb5?\x94cv\x0br\x95\xfb\xb8\x14\xe9e\xfb \xc8', 178, 1373561701L), ('\xb2\xa2vj(y\xc2\t\xab\x11v\xe7\xe7x\xb8\x1a\xe4"\xee\xaa', 138, 912998690L), ('\xf1\x8f\xaa\x16S\x1a\xc5p\xa3\xfd\xc8\xc7\xca\x16h%H\xda\xfd\x12', 12, 3775879613L)]), set(p.iterentries()))
-  
+        entries = set((sha_to_hex(s), o, c) for s, o, c in p.iterentries())
+        self.assertEquals(set([
+          ('6f670c0fb53f9463760b7295fbb814e965fb20c8', 178, 1373561701L),
+          ('b2a2766a2879c209ab1176e7e778b81ae422eeaa', 138, 912998690L),
+          ('f18faa16531ac570a3fdc8c7ca16682548dafd12', 12, 3775879613L),
+          ]), entries)
+
     def test_create_index_v1(self):
         p = self.get_pack_data(pack1_sha)
-        p.create_index_v1("v1test.idx")
-        idx1 = load_pack_index("v1test.idx")
+        filename = os.path.join(self.tempdir, 'v1test.idx')
+        p.create_index_v1(filename)
+        idx1 = load_pack_index(filename)
         idx2 = self.get_pack_index(pack1_sha)
         self.assertEquals(idx1, idx2)
-  
+
     def test_create_index_v2(self):
         p = self.get_pack_data(pack1_sha)
-        p.create_index_v2("v2test.idx")
-        idx1 = load_pack_index("v2test.idx")
+        filename = os.path.join(self.tempdir, 'v2test.idx')
+        p.create_index_v2(filename)
+        idx1 = load_pack_index(filename)
         idx2 = self.get_pack_index(pack1_sha)
         self.assertEquals(idx1, idx2)
 
@@ -182,36 +261,47 @@
         """Tests random access for non-delta objects"""
         p = self.get_pack(pack1_sha)
         obj = p[a_sha]
-        self.assertEqual(obj._type, 'blob')
+        self.assertEqual(obj.type_name, 'blob')
         self.assertEqual(obj.sha().hexdigest(), a_sha)
         obj = p[tree_sha]
-        self.assertEqual(obj._type, 'tree')
+        self.assertEqual(obj.type_name, 'tree')
         self.assertEqual(obj.sha().hexdigest(), tree_sha)
         obj = p[commit_sha]
-        self.assertEqual(obj._type, 'commit')
+        self.assertEqual(obj.type_name, 'commit')
         self.assertEqual(obj.sha().hexdigest(), commit_sha)
 
     def test_copy(self):
         origpack = self.get_pack(pack1_sha)
-        self.assertEquals(True, origpack.index.check())
-        write_pack("Elch", [(x, "") for x in origpack.iterobjects()], 
-            len(origpack))
-        newpack = Pack("Elch")
-        self.assertEquals(origpack, newpack)
-        self.assertEquals(True, newpack.index.check())
-        self.assertEquals(origpack.name(), newpack.name())
-        self.assertEquals(origpack.index.get_pack_checksum(), 
-                          newpack.index.get_pack_checksum())
-        
-        self.assertTrue(
-                (origpack.index.version != newpack.index.version) or
-                (origpack.index.get_stored_checksum() == newpack.index.get_stored_checksum()))
+
+        try:
+            self.assertSucceeds(origpack.index.check)
+            basename = os.path.join(self.tempdir, 'Elch')
+            write_pack(basename, [(x, '') for x in origpack.iterobjects()],
+                       len(origpack))
+            newpack = Pack(basename)
+
+            try:
+                self.assertEquals(origpack, newpack)
+                self.assertSucceeds(newpack.index.check)
+                self.assertEquals(origpack.name(), newpack.name())
+                self.assertEquals(origpack.index.get_pack_checksum(),
+                                  newpack.index.get_pack_checksum())
+
+                wrong_version = origpack.index.version != newpack.index.version
+                orig_checksum = origpack.index.get_stored_checksum()
+                new_checksum = newpack.index.get_stored_checksum()
+                self.assertTrue(wrong_version or orig_checksum == new_checksum)
+            finally:
+                newpack.close()
+        finally:
+            origpack.close()
+
 
     def test_commit_obj(self):
         p = self.get_pack(pack1_sha)
         commit = p[commit_sha]
-        self.assertEquals("James Westby <jw+debian@xxxxxxxxxxxxxxx>",
-            commit.author)
+        self.assertEquals('James Westby <jw+debian@xxxxxxxxxxxxxxx>',
+                          commit.author)
         self.assertEquals([], commit.parents)
 
     def test_name(self):
@@ -219,69 +309,180 @@
         self.assertEquals(pack1_sha, p.name())
 
 
-class TestHexToSha(unittest.TestCase):
+class WritePackHeaderTests(TestCase):
 
     def test_simple(self):
-        self.assertEquals('\xab\xcd' * 10, hex_to_sha("abcd" * 10))
-
-    def test_reverse(self):
-        self.assertEquals("abcd" * 10, sha_to_hex('\xab\xcd' * 10))
+        f = StringIO()
+        write_pack_header(f, 42)
+        self.assertEquals('PACK\x00\x00\x00\x02\x00\x00\x00*',
+                f.getvalue())
+
+
+pack_checksum = hex_to_sha('721980e866af9a5f93ad674144e1459b8ba3e7b7')
 
 
 class BaseTestPackIndexWriting(object):
 
+    def assertSucceeds(self, func, *args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except ChecksumMismatch, e:
+            self.fail(e)
+
+    def index(self, filename, entries, pack_checksum):
+        raise NotImplementedError(self.index)
+
     def test_empty(self):
-        pack_checksum = 'r\x19\x80\xe8f\xaf\x9a_\x93\xadgAD\xe1E\x9b\x8b\xa3\xe7\xb7'
-        self._write_fn("empty.idx", [], pack_checksum)
-        idx = load_pack_index("empty.idx")
-        self.assertTrue(idx.check())
+        idx = self.index('empty.idx', [], pack_checksum)
         self.assertEquals(idx.get_pack_checksum(), pack_checksum)
         self.assertEquals(0, len(idx))
 
     def test_single(self):
-        pack_checksum = 'r\x19\x80\xe8f\xaf\x9a_\x93\xadgAD\xe1E\x9b\x8b\xa3\xe7\xb7'
-        my_entries = [('og\x0c\x0f\xb5?\x94cv\x0br\x95\xfb\xb8\x14\xe9e\xfb \xc8', 178, 42)]
-        my_entries.sort()
-        self._write_fn("single.idx", my_entries, pack_checksum)
-        idx = load_pack_index("single.idx")
-        self.assertEquals(idx.version, self._expected_version)
-        self.assertTrue(idx.check())
+        entry_sha = hex_to_sha('6f670c0fb53f9463760b7295fbb814e965fb20c8')
+        my_entries = [(entry_sha, 178, 42)]
+        idx = self.index('single.idx', my_entries, pack_checksum)
         self.assertEquals(idx.get_pack_checksum(), pack_checksum)
         self.assertEquals(1, len(idx))
         actual_entries = list(idx.iterentries())
         self.assertEquals(len(my_entries), len(actual_entries))
-        for a, b in zip(my_entries, actual_entries):
-            self.assertEquals(a[0], b[0])
-            self.assertEquals(a[1], b[1])
+        for mine, actual in zip(my_entries, actual_entries):
+            my_sha, my_offset, my_crc = mine
+            actual_sha, actual_offset, actual_crc = actual
+            self.assertEquals(my_sha, actual_sha)
+            self.assertEquals(my_offset, actual_offset)
             if self._has_crc32_checksum:
-                self.assertEquals(a[2], b[2])
+                self.assertEquals(my_crc, actual_crc)
             else:
-                self.assertTrue(b[2] is None)
-
-
-class TestPackIndexWritingv1(unittest.TestCase, BaseTestPackIndexWriting):
-
-    def setUp(self):
-        unittest.TestCase.setUp(self)
+                self.assertTrue(actual_crc is None)
+
+
+class BaseTestFilePackIndexWriting(BaseTestPackIndexWriting):
+
+    def setUp(self):
+        self.tempdir = tempfile.mkdtemp()
+
+    def tearDown(self):
+        shutil.rmtree(self.tempdir)
+
+    def index(self, filename, entries, pack_checksum):
+        path = os.path.join(self.tempdir, filename)
+        self.writeIndex(path, entries, pack_checksum)
+        idx = load_pack_index(path)
+        self.assertSucceeds(idx.check)
+        self.assertEquals(idx.version, self._expected_version)
+        return idx
+
+    def writeIndex(self, filename, entries, pack_checksum):
+        # FIXME: Write to StringIO instead rather than hitting disk ?
+        f = GitFile(filename, "wb")
+        try:
+            self._write_fn(f, entries, pack_checksum)
+        finally:
+            f.close()
+
+
+class TestMemoryIndexWriting(TestCase, BaseTestPackIndexWriting):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self._has_crc32_checksum = True
+
+    def index(self, filename, entries, pack_checksum):
+        return MemoryPackIndex(entries, pack_checksum)
+
+    def tearDown(self):
+        TestCase.tearDown(self)
+
+
+class TestPackIndexWritingv1(TestCase, BaseTestFilePackIndexWriting):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        BaseTestFilePackIndexWriting.setUp(self)
         self._has_crc32_checksum = False
         self._expected_version = 1
         self._write_fn = write_pack_index_v1
 
-
-class TestPackIndexWritingv2(unittest.TestCase, BaseTestPackIndexWriting):
+    def tearDown(self):
+        TestCase.tearDown(self)
+        BaseTestFilePackIndexWriting.tearDown(self)
+
+
+class TestPackIndexWritingv2(TestCase, BaseTestFilePackIndexWriting):
 
     def setUp(self):
-        unittest.TestCase.setUp(self)
+        TestCase.setUp(self)
+        BaseTestFilePackIndexWriting.setUp(self)
         self._has_crc32_checksum = True
         self._expected_version = 2
         self._write_fn = write_pack_index_v2
 
-TEST_COMP1 = """\x78\x9c\x9d\x8e\xc1\x0a\xc2\x30\x10\x44\xef\xf9\x8a\xbd\xa9\x08\x92\x86\xb4\x26\x20\xe2\xd9\x83\x78\xf2\xbe\x49\x37\xb5\xa5\x69\xca\x36\xf5\xfb\x4d\xfd\x04\x67\x6e\x33\xcc\xf0\x32\x13\x81\xc6\x16\x8d\xa9\xbd\xad\x6c\xe3\x8a\x03\x4a\x73\xd6\xda\xd5\xa6\x51\x2e\x58\x65\x6c\x13\xbc\x94\x4a\xcc\xc8\x34\x65\x78\xa4\x89\x04\xae\xf9\x9d\x18\xee\x34\x46\x62\x78\x11\x4f\x29\xf5\x03\x5c\x86\x5f\x70\x5b\x30\x3a\x3c\x25\xee\xae\x50\xa9\xf2\x60\xa4\xaa\x34\x1c\x65\x91\xf0\x29\xc6\x3e\x67\xfa\x6f\x2d\x9e\x9c\x3e\x7d\x4b\xc0\x34\x8f\xe8\x29\x6e\x48\xa1\xa0\xc4\x88\xf3\xfe\xb0\x5b\x20\x85\xb0\x50\x06\xe4\x6e\xdd\xca\xd3\x17\x26\xfa\x49\x23"""
-
-
-class ZlibTests(unittest.TestCase):
+    def tearDown(self):
+        TestCase.tearDown(self)
+        BaseTestFilePackIndexWriting.tearDown(self)
+
+
+class ReadZlibTests(TestCase):
+
+    decomp = (
+      'tree 4ada885c9196b6b6fa08744b5862bf92896fc002\n'
+      'parent None\n'
+      'author Jelmer Vernooij <jelmer@xxxxxxxxx> 1228980214 +0000\n'
+      'committer Jelmer Vernooij <jelmer@xxxxxxxxx> 1228980214 +0000\n'
+      '\n'
+      "Provide replacement for mmap()'s offset argument.")
+    comp = zlib.compress(decomp)
+    extra = 'nextobject'
+
+    def setUp(self):
+        super(ReadZlibTests, self).setUp()
+        self.read = StringIO(self.comp + self.extra).read
+
+    def test_decompress_size(self):
+        good_decomp_len = len(self.decomp)
+        self.assertRaises(ValueError, read_zlib_chunks, self.read, -1)
+        self.assertRaises(zlib.error, read_zlib_chunks, self.read,
+                          good_decomp_len - 1)
+        self.assertRaises(zlib.error, read_zlib_chunks, self.read,
+                          good_decomp_len + 1)
+
+    def test_decompress_truncated(self):
+        read = StringIO(self.comp[:10]).read
+        self.assertRaises(zlib.error, read_zlib_chunks, read, len(self.decomp))
+
+        read = StringIO(self.comp).read
+        self.assertRaises(zlib.error, read_zlib_chunks, read, len(self.decomp))
+
+    def test_decompress_empty(self):
+        comp = zlib.compress('')
+        read = StringIO(comp + self.extra).read
+        decomp, comp_len, unused_data = read_zlib_chunks(read, 0)
+        self.assertEqual('', ''.join(decomp))
+        self.assertEqual(len(comp), comp_len)
+        self.assertNotEquals('', unused_data)
+        self.assertEquals(self.extra, unused_data + read())
+
+    def _do_decompress_test(self, buffer_size):
+        decomp, comp_len, unused_data = read_zlib_chunks(
+          self.read, len(self.decomp), buffer_size=buffer_size)
+        self.assertEquals(self.decomp, ''.join(decomp))
+        self.assertEquals(len(self.comp), comp_len)
+        self.assertNotEquals('', unused_data)
+        self.assertEquals(self.extra, unused_data + self.read())
 
     def test_simple_decompress(self):
-        self.assertEquals(("tree 4ada885c9196b6b6fa08744b5862bf92896fc002\nparent None\nauthor Jelmer Vernooij <jelmer@xxxxxxxxx> 1228980214 +0000\ncommitter Jelmer Vernooij <jelmer@xxxxxxxxx> 1228980214 +0000\n\nProvide replacement for mmap()'s offset argument.", 158), 
-        read_zlib(TEST_COMP1, 0, 229))
-
+        self._do_decompress_test(4096)
+
+    # These buffer sizes are not intended to be realistic, but rather simulate
+    # larger buffer sizes that may end at various places.
+    def test_decompress_buffer_size_1(self):
+        self._do_decompress_test(1)
+
+    def test_decompress_buffer_size_2(self):
+        self._do_decompress_test(2)
+
+    def test_decompress_buffer_size_3(self):
+        self._do_decompress_test(3)
+
+    def test_decompress_buffer_size_4(self):
+        self._do_decompress_test(4)

=== added file 'dulwich/tests/test_patch.py'
--- dulwich/tests/test_patch.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/test_patch.py	2010-12-18 16:48:28 +0000
@@ -0,0 +1,292 @@
+# test_patch.py -- tests for patch.py
+# Copyright (C) 2010 Jelmer Vernooij <jelmer@xxxxxxxxx>
+#
+# 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) a later version.
+#
+# 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.
+
+"""Tests for patch.py."""
+
+from cStringIO import StringIO
+
+from dulwich.objects import (
+    Blob,
+    Commit,
+    Tree,
+    )
+from dulwich.object_store import (
+    MemoryObjectStore,
+    )
+from dulwich.patch import (
+    git_am_patch_split,
+    write_blob_diff,
+    write_commit_patch,
+    write_tree_diff,
+    )
+from dulwich.tests import (
+    TestCase,
+    TestSkipped,
+    )
+
+
+class WriteCommitPatchTests(TestCase):
+
+    def test_simple(self):
+        f = StringIO()
+        c = Commit()
+        c.committer = c.author = "Jelmer <jelmer@xxxxxxxxx>"
+        c.commit_time = c.author_time = 1271350201
+        c.commit_timezone = c.author_timezone = 0
+        c.message = "This is the first line\nAnd this is the second line.\n"
+        c.tree = Tree().id
+        write_commit_patch(f, c, "CONTENTS", (1, 1), version="custom")
+        f.seek(0)
+        lines = f.readlines()
+        self.assertTrue(lines[0].startswith("From 0b0d34d1b5b596c928adc9a727a4b9e03d025298"))
+        self.assertEquals(lines[1], "From: Jelmer <jelmer@xxxxxxxxx>\n")
+        self.assertTrue(lines[2].startswith("Date: "))
+        self.assertEquals([
+            "Subject: [PATCH 1/1] This is the first line\n",
+            "And this is the second line.\n",
+            "\n",
+            "\n",
+            "---\n"], lines[3:8])
+        self.assertEquals([
+            "CONTENTS-- \n",
+            "custom\n"], lines[-2:])
+        if len(lines) >= 12:
+            # diffstat may not be present
+            self.assertEquals(lines[8], " 0 files changed\n")
+
+
+class ReadGitAmPatch(TestCase):
+
+    def test_extract(self):
+        text = """From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
+From: Jelmer Vernooij <jelmer@xxxxxxxxx>
+Date: Thu, 15 Apr 2010 15:40:28 +0200
+Subject: [PATCH 1/2] Remove executable bit from prey.ico (triggers a lintian warning).
+
+---
+ pixmaps/prey.ico |  Bin 9662 -> 9662 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 pixmaps/prey.ico
+
+-- 
+1.7.0.4
+"""
+        c, diff, version = git_am_patch_split(StringIO(text))
+        self.assertEquals("Jelmer Vernooij <jelmer@xxxxxxxxx>", c.committer)
+        self.assertEquals("Jelmer Vernooij <jelmer@xxxxxxxxx>", c.author)
+        self.assertEquals("Remove executable bit from prey.ico "
+            "(triggers a lintian warning).\n", c.message)
+        self.assertEquals(""" pixmaps/prey.ico |  Bin 9662 -> 9662 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 pixmaps/prey.ico
+
+""", diff)
+        self.assertEquals("1.7.0.4", version)
+
+    def test_extract_spaces(self):
+        text = """From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
+From: Jelmer Vernooij <jelmer@xxxxxxxxx>
+Date: Thu, 15 Apr 2010 15:40:28 +0200
+Subject:  [Dulwich-users] [PATCH] Added unit tests for
+ dulwich.object_store.tree_lookup_path.
+
+* dulwich/tests/test_object_store.py
+  (TreeLookupPathTests): This test case contains a few tests that ensure the
+   tree_lookup_path function works as expected.
+---
+ pixmaps/prey.ico |  Bin 9662 -> 9662 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 pixmaps/prey.ico
+
+-- 
+1.7.0.4
+"""
+        c, diff, version = git_am_patch_split(StringIO(text))
+        self.assertEquals('Added unit tests for dulwich.object_store.tree_lookup_path.\n\n* dulwich/tests/test_object_store.py\n  (TreeLookupPathTests): This test case contains a few tests that ensure the\n   tree_lookup_path function works as expected.\n', c.message)
+
+    def test_extract_pseudo_from_header(self):
+        text = """From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
+From: Jelmer Vernooij <jelmer@xxxxxxxxx>
+Date: Thu, 15 Apr 2010 15:40:28 +0200
+Subject:  [Dulwich-users] [PATCH] Added unit tests for
+ dulwich.object_store.tree_lookup_path.
+
+From: Jelmer Vernooy <jelmer@xxxxxxxxxx>
+
+* dulwich/tests/test_object_store.py
+  (TreeLookupPathTests): This test case contains a few tests that ensure the
+   tree_lookup_path function works as expected.
+---
+ pixmaps/prey.ico |  Bin 9662 -> 9662 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 pixmaps/prey.ico
+
+-- 
+1.7.0.4
+"""
+        c, diff, version = git_am_patch_split(StringIO(text))
+        self.assertEquals("Jelmer Vernooy <jelmer@xxxxxxxxxx>", c.author)
+        self.assertEquals('Added unit tests for dulwich.object_store.tree_lookup_path.\n\n* dulwich/tests/test_object_store.py\n  (TreeLookupPathTests): This test case contains a few tests that ensure the\n   tree_lookup_path function works as expected.\n', c.message)
+
+    def test_extract_no_version_tail(self):
+        text = """From ff643aae102d8870cac88e8f007e70f58f3a7363 Mon Sep 17 00:00:00 2001
+From: Jelmer Vernooij <jelmer@xxxxxxxxx>
+Date: Thu, 15 Apr 2010 15:40:28 +0200
+Subject:  [Dulwich-users] [PATCH] Added unit tests for
+ dulwich.object_store.tree_lookup_path.
+
+From: Jelmer Vernooy <jelmer@xxxxxxxxxx>
+
+---
+ pixmaps/prey.ico |  Bin 9662 -> 9662 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 pixmaps/prey.ico
+
+"""
+        c, diff, version = git_am_patch_split(StringIO(text))
+        self.assertEquals(None, version)
+
+    def test_extract_mercurial(self):
+        raise TestSkipped("git_am_patch_split doesn't handle Mercurial patches properly yet")
+        expected_diff = """diff --git a/dulwich/tests/test_patch.py b/dulwich/tests/test_patch.py
+--- a/dulwich/tests/test_patch.py
++++ b/dulwich/tests/test_patch.py
+@@ -158,7 +158,7 @@
+ 
+ '''
+         c, diff, version = git_am_patch_split(StringIO(text))
+-        self.assertIs(None, version)
++        self.assertEquals(None, version)
+ 
+ 
+ class DiffTests(TestCase):
+"""
+        text = """From dulwich-users-bounces+jelmer=samba.org@xxxxxxxxxxxxxxxxxxx Mon Nov 29 00:58:18 2010
+Date: Sun, 28 Nov 2010 17:57:27 -0600
+From: Augie Fackler <durin42@xxxxxxxxx>
+To: dulwich-users <dulwich-users@xxxxxxxxxxxxxxxxxxx>
+Subject: [Dulwich-users] [PATCH] test_patch: fix tests on Python 2.6
+Content-Transfer-Encoding: 8bit
+
+Change-Id: I5e51313d4ae3a65c3f00c665002a7489121bb0d6
+
+%s
+
+_______________________________________________
+Mailing list: https://launchpad.net/~dulwich-users
+Post to     : dulwich-users@xxxxxxxxxxxxxxxxxxx
+Unsubscribe : https://launchpad.net/~dulwich-users
+More help   : https://help.launchpad.net/ListHelp
+
+""" % expected_diff
+        c, diff, version = git_am_patch_split(StringIO(text))
+        self.assertEquals(expected_diff, diff)
+        self.assertEquals(None, version)
+
+
+class DiffTests(TestCase):
+    """Tests for write_blob_diff and write_tree_diff."""
+
+    def test_blob_diff(self):
+        f = StringIO()
+        write_blob_diff(f, ("foo.txt", 0644, Blob.from_string("old\nsame\n")),
+                           ("bar.txt", 0644, Blob.from_string("new\nsame\n")))
+        self.assertEquals([
+            "diff --git a/foo.txt b/bar.txt",
+            "index 3b0f961..a116b51 644",
+            "--- a/foo.txt",
+            "+++ b/bar.txt",
+            "@@ -1,2 +1,2 @@",
+            "-old",
+            "+new",
+            " same"
+            ], f.getvalue().splitlines())
+
+    def test_blob_add(self):
+        f = StringIO()
+        write_blob_diff(f, (None, None, None),
+                           ("bar.txt", 0644, Blob.from_string("new\nsame\n")))
+        self.assertEquals([
+            'diff --git /dev/null b/bar.txt',
+             'new mode 644',
+             'index 0000000..a116b51 644',
+             '--- /dev/null',
+             '+++ b/bar.txt',
+             '@@ -1,0 +1,2 @@',
+             '+new',
+             '+same'
+            ], f.getvalue().splitlines())
+
+    def test_blob_remove(self):
+        f = StringIO()
+        write_blob_diff(f, ("bar.txt", 0644, Blob.from_string("new\nsame\n")),
+                           (None, None, None))
+        self.assertEquals([
+            'diff --git a/bar.txt /dev/null',
+            'deleted mode 644',
+            'index a116b51..0000000',
+            '--- a/bar.txt',
+            '+++ /dev/null',
+            '@@ -1,2 +1,0 @@',
+            '-new',
+            '-same'
+            ], f.getvalue().splitlines())
+
+    def test_tree_diff(self):
+        f = StringIO()
+        store = MemoryObjectStore()
+        added = Blob.from_string("add\n")
+        removed = Blob.from_string("removed\n")
+        changed1 = Blob.from_string("unchanged\nremoved\n")
+        changed2 = Blob.from_string("unchanged\nadded\n")
+        unchanged = Blob.from_string("unchanged\n")
+        tree1 = Tree()
+        tree1.add(0644, "removed.txt", removed.id)
+        tree1.add(0644, "changed.txt", changed1.id)
+        tree1.add(0644, "unchanged.txt", changed1.id)
+        tree2 = Tree()
+        tree2.add(0644, "added.txt", added.id)
+        tree2.add(0644, "changed.txt", changed2.id)
+        tree2.add(0644, "unchanged.txt", changed1.id)
+        store.add_objects([(o, None) for o in [
+            tree1, tree2, added, removed, changed1, changed2, unchanged]])
+        write_tree_diff(f, store, tree1.id, tree2.id)
+        self.assertEquals([
+            'diff --git /dev/null b/added.txt',
+            'new mode 644',
+            'index e69de29..76d4bb8 644',
+            '--- /dev/null',
+            '+++ b/added.txt',
+            '@@ -1,0 +1,1 @@',
+            '+add',
+            'diff --git a/changed.txt b/changed.txt',
+            'index bf84e48..1be2436 644',
+            '--- a/changed.txt',
+            '+++ b/changed.txt',
+            '@@ -1,2 +1,2 @@',
+            ' unchanged',
+            '-removed',
+            '+added',
+            'diff --git a/removed.txt /dev/null',
+            'deleted mode 644',
+            'index 2c3f0b3..e69de29',
+            '--- a/removed.txt',
+            '+++ /dev/null',
+            '@@ -1,1 +1,0 @@',
+            '-removed',
+            ], f.getvalue().splitlines())

=== modified file 'dulwich/tests/test_protocol.py'
--- dulwich/tests/test_protocol.py	2009-05-19 19:09:14 +0000
+++ dulwich/tests/test_protocol.py	2010-10-05 18:00:47 +0000
@@ -1,86 +1,282 @@
 # test_protocol.py -- Tests for the git protocol
 # Copyright (C) 2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
-# 
+#
 # 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
 # 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.
 
-
 """Tests for the smart protocol utility functions."""
 
 
-from cStringIO import StringIO
-from unittest import TestCase
+from StringIO import StringIO
 
+from dulwich.errors import (
+    HangupException,
+    )
 from dulwich.protocol import (
     Protocol,
+    ReceivableProtocol,
     extract_capabilities,
+    extract_want_line_capabilities,
+    ack_type,
+    SINGLE_ACK,
+    MULTI_ACK,
+    MULTI_ACK_DETAILED,
+    BufferedPktLineWriter,
     )
-
-class ProtocolTests(TestCase):
-
-    def setUp(self):
-        self.rout = StringIO()
-        self.rin = StringIO()
-        self.proto = Protocol(self.rin.read, self.rout.write)
+from dulwich.tests import TestCase
+
+
+class BaseProtocolTests(object):
 
     def test_write_pkt_line_none(self):
         self.proto.write_pkt_line(None)
-        self.assertEquals(self.rout.getvalue(), "0000")
+        self.assertEquals(self.rout.getvalue(), '0000')
 
     def test_write_pkt_line(self):
-        self.proto.write_pkt_line("bla")
-        self.assertEquals(self.rout.getvalue(), "0007bla")
+        self.proto.write_pkt_line('bla')
+        self.assertEquals(self.rout.getvalue(), '0007bla')
 
     def test_read_pkt_line(self):
-        self.rin.write("0008cmd ")
-        self.rin.seek(0)
-        self.assertEquals("cmd ", self.proto.read_pkt_line())
+        self.rin.write('0008cmd ')
+        self.rin.seek(0)
+        self.assertEquals('cmd ', self.proto.read_pkt_line())
+
+    def test_eof(self):
+        self.rin.write('0000')
+        self.rin.seek(0)
+        self.assertFalse(self.proto.eof())
+        self.assertEquals(None, self.proto.read_pkt_line())
+        self.assertTrue(self.proto.eof())
+        self.assertRaises(HangupException, self.proto.read_pkt_line)
+
+    def test_unread_pkt_line(self):
+        self.rin.write('0007foo0000')
+        self.rin.seek(0)
+        self.assertEquals('foo', self.proto.read_pkt_line())
+        self.proto.unread_pkt_line('bar')
+        self.assertEquals('bar', self.proto.read_pkt_line())
+        self.assertEquals(None, self.proto.read_pkt_line())
+        self.proto.unread_pkt_line('baz1')
+        self.assertRaises(ValueError, self.proto.unread_pkt_line, 'baz2')
 
     def test_read_pkt_seq(self):
-        self.rin.write("0008cmd 0005l0000")
+        self.rin.write('0008cmd 0005l0000')
         self.rin.seek(0)
-        self.assertEquals(["cmd ", "l"], list(self.proto.read_pkt_seq()))
+        self.assertEquals(['cmd ', 'l'], list(self.proto.read_pkt_seq()))
 
     def test_read_pkt_line_none(self):
-        self.rin.write("0000")
+        self.rin.write('0000')
         self.rin.seek(0)
         self.assertEquals(None, self.proto.read_pkt_line())
 
     def test_write_sideband(self):
-        self.proto.write_sideband(3, "bloe")
-        self.assertEquals(self.rout.getvalue(), "0009\x03bloe")
+        self.proto.write_sideband(3, 'bloe')
+        self.assertEquals(self.rout.getvalue(), '0009\x03bloe')
 
     def test_send_cmd(self):
-        self.proto.send_cmd("fetch", "a", "b")
-        self.assertEquals(self.rout.getvalue(), "000efetch a\x00b\x00")
+        self.proto.send_cmd('fetch', 'a', 'b')
+        self.assertEquals(self.rout.getvalue(), '000efetch a\x00b\x00')
 
     def test_read_cmd(self):
-        self.rin.write("0012cmd arg1\x00arg2\x00")
+        self.rin.write('0012cmd arg1\x00arg2\x00')
         self.rin.seek(0)
-        self.assertEquals(("cmd", ["arg1", "arg2"]), self.proto.read_cmd())
+        self.assertEquals(('cmd', ['arg1', 'arg2']), self.proto.read_cmd())
 
     def test_read_cmd_noend0(self):
-        self.rin.write("0011cmd arg1\x00arg2")
+        self.rin.write('0011cmd arg1\x00arg2')
         self.rin.seek(0)
         self.assertRaises(AssertionError, self.proto.read_cmd)
 
 
-class ExtractCapabilitiesTestCase(TestCase):
+class ProtocolTests(BaseProtocolTests, TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self.rout = StringIO()
+        self.rin = StringIO()
+        self.proto = Protocol(self.rin.read, self.rout.write)
+
+
+class ReceivableStringIO(StringIO):
+    """StringIO with socket-like recv semantics for testing."""
+
+    def __init__(self):
+        StringIO.__init__(self)
+        self.allow_read_past_eof = False
+
+    def recv(self, size):
+        # fail fast if no bytes are available; in a real socket, this would
+        # block forever
+        if self.tell() == len(self.getvalue()) and not self.allow_read_past_eof:
+            raise AssertionError('Blocking read past end of socket')
+        if size == 1:
+            return self.read(1)
+        # calls shouldn't return quite as much as asked for
+        return self.read(size - 1)
+
+
+class ReceivableProtocolTests(BaseProtocolTests, TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self.rout = StringIO()
+        self.rin = ReceivableStringIO()
+        self.proto = ReceivableProtocol(self.rin.recv, self.rout.write)
+        self.proto._rbufsize = 8
+
+    def test_eof(self):
+        # Allow blocking reads past EOF just for this test. The only parts of
+        # the protocol that might check for EOF do not depend on the recv()
+        # semantics anyway.
+        self.rin.allow_read_past_eof = True
+        BaseProtocolTests.test_eof(self)
+
+    def test_recv(self):
+        all_data = '1234567' * 10  # not a multiple of bufsize
+        self.rin.write(all_data)
+        self.rin.seek(0)
+        data = ''
+        # We ask for 8 bytes each time and actually read 7, so it should take
+        # exactly 10 iterations.
+        for _ in xrange(10):
+            data += self.proto.recv(10)
+        # any more reads would block
+        self.assertRaises(AssertionError, self.proto.recv, 10)
+        self.assertEquals(all_data, data)
+
+    def test_recv_read(self):
+        all_data = '1234567'  # recv exactly in one call
+        self.rin.write(all_data)
+        self.rin.seek(0)
+        self.assertEquals('1234', self.proto.recv(4))
+        self.assertEquals('567', self.proto.read(3))
+        self.assertRaises(AssertionError, self.proto.recv, 10)
+
+    def test_read_recv(self):
+        all_data = '12345678abcdefg'
+        self.rin.write(all_data)
+        self.rin.seek(0)
+        self.assertEquals('1234', self.proto.read(4))
+        self.assertEquals('5678abc', self.proto.recv(8))
+        self.assertEquals('defg', self.proto.read(4))
+        self.assertRaises(AssertionError, self.proto.recv, 10)
+
+    def test_mixed(self):
+        # arbitrary non-repeating string
+        all_data = ','.join(str(i) for i in xrange(100))
+        self.rin.write(all_data)
+        self.rin.seek(0)
+        data = ''
+
+        for i in xrange(1, 100):
+            data += self.proto.recv(i)
+            # if we get to the end, do a non-blocking read instead of blocking
+            if len(data) + i > len(all_data):
+                data += self.proto.recv(i)
+                # ReceivableStringIO leaves off the last byte unless we ask
+                # nicely
+                data += self.proto.recv(1)
+                break
+            else:
+                data += self.proto.read(i)
+        else:
+            # didn't break, something must have gone wrong
+            self.fail()
+
+        self.assertEquals(all_data, data)
+
+
+class CapabilitiesTestCase(TestCase):
 
     def test_plain(self):
-        self.assertEquals(("bla", None), extract_capabilities("bla"))
+        self.assertEquals(('bla', []), extract_capabilities('bla'))
 
     def test_caps(self):
-        self.assertEquals(("bla", ["la", "la"]), extract_capabilities("bla\0la\0la"))
+        self.assertEquals(('bla', ['la']), extract_capabilities('bla\0la'))
+        self.assertEquals(('bla', ['la']), extract_capabilities('bla\0la\n'))
+        self.assertEquals(('bla', ['la', 'la']), extract_capabilities('bla\0la la'))
+
+    def test_plain_want_line(self):
+        self.assertEquals(('want bla', []), extract_want_line_capabilities('want bla'))
+
+    def test_caps_want_line(self):
+        self.assertEquals(('want bla', ['la']), extract_want_line_capabilities('want bla la'))
+        self.assertEquals(('want bla', ['la']), extract_want_line_capabilities('want bla la\n'))
+        self.assertEquals(('want bla', ['la', 'la']), extract_want_line_capabilities('want bla la la'))
+
+    def test_ack_type(self):
+        self.assertEquals(SINGLE_ACK, ack_type(['foo', 'bar']))
+        self.assertEquals(MULTI_ACK, ack_type(['foo', 'bar', 'multi_ack']))
+        self.assertEquals(MULTI_ACK_DETAILED,
+                          ack_type(['foo', 'bar', 'multi_ack_detailed']))
+        # choose detailed when both present
+        self.assertEquals(MULTI_ACK_DETAILED,
+                          ack_type(['foo', 'bar', 'multi_ack',
+                                    'multi_ack_detailed']))
+
+
+class BufferedPktLineWriterTests(TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self._output = StringIO()
+        self._writer = BufferedPktLineWriter(self._output.write, bufsize=16)
+
+    def assertOutputEquals(self, expected):
+        self.assertEquals(expected, self._output.getvalue())
+
+    def _truncate(self):
+        self._output.seek(0)
+        self._output.truncate()
+
+    def test_write(self):
+        self._writer.write('foo')
+        self.assertOutputEquals('')
+        self._writer.flush()
+        self.assertOutputEquals('0007foo')
+
+    def test_write_none(self):
+        self._writer.write(None)
+        self.assertOutputEquals('')
+        self._writer.flush()
+        self.assertOutputEquals('0000')
+
+    def test_flush_empty(self):
+        self._writer.flush()
+        self.assertOutputEquals('')
+
+    def test_write_multiple(self):
+        self._writer.write('foo')
+        self._writer.write('bar')
+        self.assertOutputEquals('')
+        self._writer.flush()
+        self.assertOutputEquals('0007foo0007bar')
+
+    def test_write_across_boundary(self):
+        self._writer.write('foo')
+        self._writer.write('barbaz')
+        self.assertOutputEquals('0007foo000abarba')
+        self._truncate()
+        self._writer.flush()
+        self.assertOutputEquals('z')
+
+    def test_write_to_boundary(self):
+        self._writer.write('foo')
+        self._writer.write('barba')
+        self.assertOutputEquals('0007foo0009barba')
+        self._truncate()
+        self._writer.write('z')
+        self._writer.flush()
+        self.assertOutputEquals('0005z')

=== modified file 'dulwich/tests/test_repository.py'
--- dulwich/tests/test_repository.py	2009-06-16 13:17:14 +0000
+++ dulwich/tests/test_repository.py	2011-01-17 06:00:40 +0000
@@ -1,114 +1,270 @@
 # test_repository.py -- tests for repository.py
 # Copyright (C) 2007 James Westby <jw+debian@xxxxxxxxxxxxxxx>
-# 
+#
 # 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 
+# 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.
 
-
 """Tests for the repository."""
 
-
+from cStringIO import StringIO
 import os
-import unittest
+import shutil
+import tempfile
+import warnings
 
 from dulwich import errors
-from dulwich.repo import Repo
+from dulwich.file import (
+    GitFile,
+    )
+from dulwich.object_store import (
+    tree_lookup_path,
+    )
+from dulwich import objects
+from dulwich.repo import (
+    check_ref_format,
+    DictRefsContainer,
+    Repo,
+    MemoryRepo,
+    read_packed_refs,
+    read_packed_refs_with_peeled,
+    write_packed_refs,
+    _split_ref_line,
+    )
+from dulwich.tests import (
+    TestCase,
+    )
+from dulwich.tests.utils import (
+    open_repo,
+    tear_down_repo,
+    )
 
 missing_sha = 'b91fa4d900e17e99b433218e988c4eb4a3e9a097'
 
-class RepositoryTests(unittest.TestCase):
-  
-    def open_repo(self, name):
-        return Repo(os.path.join(os.path.dirname(__file__),
-                          'data', 'repos', name))
-  
+
+class CreateRepositoryTests(TestCase):
+
+    def assertFileContentsEqual(self, expected, repo, path):
+        f = repo.get_named_file(path)
+        if not f:
+            self.assertEqual(expected, None)
+        else:
+            try:
+                self.assertEqual(expected, f.read())
+            finally:
+                f.close()
+
+    def _check_repo_contents(self, repo, expect_bare):
+        self.assertEquals(expect_bare, repo.bare)
+        self.assertFileContentsEqual('Unnamed repository', repo, 'description')
+        self.assertFileContentsEqual('', repo, os.path.join('info', 'exclude'))
+        self.assertFileContentsEqual(None, repo, 'nonexistent file')
+        barestr = 'bare = %s' % str(expect_bare).lower()
+        self.assertTrue(barestr in repo.get_named_file('config').read())
+
+    def test_create_disk_bare(self):
+        tmp_dir = tempfile.mkdtemp()
+        try:
+            repo = Repo.init_bare(tmp_dir)
+            self.assertEquals(tmp_dir, repo._controldir)
+            self._check_repo_contents(repo, True)
+        finally:
+            shutil.rmtree(tmp_dir)
+
+    def test_create_disk_non_bare(self):
+        tmp_dir = tempfile.mkdtemp()
+        try:
+            repo = Repo.init(tmp_dir)
+            self.assertEquals(os.path.join(tmp_dir, '.git'), repo._controldir)
+            self._check_repo_contents(repo, False)
+        finally:
+            shutil.rmtree(tmp_dir)
+
+    def test_create_memory(self):
+        repo = MemoryRepo.init_bare([], {})
+        self._check_repo_contents(repo, True)
+
+
+class RepositoryTests(TestCase):
+
+    def setUp(self):
+        super(RepositoryTests, self).setUp()
+        self._repo = None
+
+    def tearDown(self):
+        if self._repo is not None:
+            tear_down_repo(self._repo)
+        super(RepositoryTests, self).tearDown()
+
     def test_simple_props(self):
-        r = self.open_repo('a.git')
-        basedir = os.path.join(os.path.dirname(__file__), 
-                os.path.join('data', 'repos', 'a.git'))
-        self.assertEqual(r.controldir(), basedir)
-  
+        r = self._repo = open_repo('a.git')
+        self.assertEqual(r.controldir(), r.path)
+
     def test_ref(self):
-        r = self.open_repo('a.git')
+        r = self._repo = open_repo('a.git')
         self.assertEqual(r.ref('refs/heads/master'),
                          'a90fa2d900a17e99b433217e988c4eb4a2e9a097')
-  
+
+    def test_setitem(self):
+        r = self._repo = open_repo('a.git')
+        r["refs/tags/foo"] = 'a90fa2d900a17e99b433217e988c4eb4a2e9a097'
+        self.assertEquals('a90fa2d900a17e99b433217e988c4eb4a2e9a097',
+                          r["refs/tags/foo"].id)
+
     def test_get_refs(self):
-        r = self.open_repo('a.git')
-        self.assertEquals({
-            'HEAD': 'a90fa2d900a17e99b433217e988c4eb4a2e9a097', 
-            'refs/heads/master': 'a90fa2d900a17e99b433217e988c4eb4a2e9a097'
+        r = self._repo = open_repo('a.git')
+        self.assertEqual({
+            'HEAD': 'a90fa2d900a17e99b433217e988c4eb4a2e9a097',
+            'refs/heads/master': 'a90fa2d900a17e99b433217e988c4eb4a2e9a097',
+            'refs/tags/mytag': '28237f4dc30d0d462658d6b937b08a0f0b6ef55a',
+            'refs/tags/mytag-packed': 'b0931cadc54336e78a1d980420e3268903b57a50',
             }, r.get_refs())
-  
+
     def test_head(self):
-        r = self.open_repo('a.git')
+        r = self._repo = open_repo('a.git')
         self.assertEqual(r.head(), 'a90fa2d900a17e99b433217e988c4eb4a2e9a097')
-  
+
     def test_get_object(self):
-        r = self.open_repo('a.git')
+        r = self._repo = open_repo('a.git')
         obj = r.get_object(r.head())
-        self.assertEqual(obj._type, 'commit')
-  
+        self.assertEqual(obj.type_name, 'commit')
+
     def test_get_object_non_existant(self):
-        r = self.open_repo('a.git')
+        r = self._repo = open_repo('a.git')
         self.assertRaises(KeyError, r.get_object, missing_sha)
-  
+
+    def test_contains_object(self):
+        r = self._repo = open_repo('a.git')
+        self.assertTrue(r.head() in r)
+
+    def test_contains_ref(self):
+        r = self._repo = open_repo('a.git')
+        self.assertTrue("HEAD" in r)
+
+    def test_contains_missing(self):
+        r = self._repo = open_repo('a.git')
+        self.assertFalse("bar" in r)
+
     def test_commit(self):
-        r = self.open_repo('a.git')
-        obj = r.commit(r.head())
-        self.assertEqual(obj._type, 'commit')
-  
+        r = self._repo = open_repo('a.git')
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            obj = r.commit(r.head())
+        finally:
+            warnings.resetwarnings()
+        self.assertEqual(obj.type_name, 'commit')
+
     def test_commit_not_commit(self):
-        r = self.open_repo('a.git')
-        self.assertRaises(errors.NotCommitError,
-                          r.commit, '4f2e6529203aa6d44b5af6e3292c837ceda003f9')
-  
+        r = self._repo = open_repo('a.git')
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            self.assertRaises(errors.NotCommitError,
+                r.commit, '4f2e6529203aa6d44b5af6e3292c837ceda003f9')
+        finally:
+            warnings.resetwarnings()
+
     def test_tree(self):
-        r = self.open_repo('a.git')
-        commit = r.commit(r.head())
-        tree = r.tree(commit.tree)
-        self.assertEqual(tree._type, 'tree')
+        r = self._repo = open_repo('a.git')
+        commit = r[r.head()]
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            tree = r.tree(commit.tree)
+        finally:
+            warnings.resetwarnings()
+        self.assertEqual(tree.type_name, 'tree')
         self.assertEqual(tree.sha().hexdigest(), commit.tree)
-  
+
     def test_tree_not_tree(self):
-        r = self.open_repo('a.git')
-        self.assertRaises(errors.NotTreeError, r.tree, r.head())
-  
+        r = self._repo = open_repo('a.git')
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            self.assertRaises(errors.NotTreeError, r.tree, r.head())
+        finally:
+            warnings.resetwarnings()
+
+    def test_tag(self):
+        r = self._repo = open_repo('a.git')
+        tag_sha = '28237f4dc30d0d462658d6b937b08a0f0b6ef55a'
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            tag = r.tag(tag_sha)
+        finally:
+            warnings.resetwarnings()
+        self.assertEqual(tag.type_name, 'tag')
+        self.assertEqual(tag.sha().hexdigest(), tag_sha)
+        obj_class, obj_sha = tag.object
+        self.assertEqual(obj_class, objects.Commit)
+        self.assertEqual(obj_sha, r.head())
+
+    def test_tag_not_tag(self):
+        r = self._repo = open_repo('a.git')
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            self.assertRaises(errors.NotTagError, r.tag, r.head())
+        finally:
+            warnings.resetwarnings()
+
+    def test_get_peeled(self):
+        # unpacked ref
+        r = self._repo = open_repo('a.git')
+        tag_sha = '28237f4dc30d0d462658d6b937b08a0f0b6ef55a'
+        self.assertNotEqual(r[tag_sha].sha().hexdigest(), r.head())
+        self.assertEqual(r.get_peeled('refs/tags/mytag'), r.head())
+
+        # packed ref with cached peeled value
+        packed_tag_sha = 'b0931cadc54336e78a1d980420e3268903b57a50'
+        parent_sha = r[r.head()].parents[0]
+        self.assertNotEqual(r[packed_tag_sha].sha().hexdigest(), parent_sha)
+        self.assertEqual(r.get_peeled('refs/tags/mytag-packed'), parent_sha)
+
+        # TODO: add more corner cases to test repo
+
+    def test_get_peeled_not_tag(self):
+        r = self._repo = open_repo('a.git')
+        self.assertEqual(r.get_peeled('HEAD'), r.head())
+
     def test_get_blob(self):
-        r = self.open_repo('a.git')
-        commit = r.commit(r.head())
-        tree = r.tree(commit.tree())
+        r = self._repo = open_repo('a.git')
+        commit = r[r.head()]
+        tree = r[commit.tree]
         blob_sha = tree.entries()[0][2]
-        blob = r.get_blob(blob_sha)
-        self.assertEqual(blob._type, 'blob')
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            blob = r.get_blob(blob_sha)
+        finally:
+            warnings.resetwarnings()
+        self.assertEqual(blob.type_name, 'blob')
         self.assertEqual(blob.sha().hexdigest(), blob_sha)
-  
-    def test_get_blob(self):
-        r = self.open_repo('a.git')
-        self.assertRaises(errors.NotBlobError, r.get_blob, r.head())
-    
+
+    def test_get_blob_notblob(self):
+        r = self._repo = open_repo('a.git')
+        warnings.simplefilter("ignore", DeprecationWarning)
+        try:
+            self.assertRaises(errors.NotBlobError, r.get_blob, r.head())
+        finally:
+            warnings.resetwarnings()
+
     def test_linear_history(self):
-        r = self.open_repo('a.git')
+        r = self._repo = open_repo('a.git')
         history = r.revision_history(r.head())
         shas = [c.sha().hexdigest() for c in history]
         self.assertEqual(shas, [r.head(),
                                 '2a72d929692c41d8554c07f6301757ba18a65d91'])
-  
+
     def test_merge_history(self):
-        r = self.open_repo('simple_merge.git')
+        r = self._repo = open_repo('simple_merge.git')
         history = r.revision_history(r.head())
         shas = [c.sha().hexdigest() for c in history]
         self.assertEqual(shas, ['5dac377bdded4c9aeb8dff595f0faeebcc8498cc',
@@ -116,22 +272,553 @@
                                 '4cffe90e0a41ad3f5190079d7c8f036bde29cbe6',
                                 '60dacdc733de308bb77bb76ce0fb0f9b44c9769e',
                                 '0d89f20333fbb1d2f3a94da77f4981373d8f4310'])
-  
+
     def test_revision_history_missing_commit(self):
-        r = self.open_repo('simple_merge.git')
+        r = self._repo = open_repo('simple_merge.git')
         self.assertRaises(errors.MissingCommitError, r.revision_history,
                           missing_sha)
-  
+
     def test_out_of_order_merge(self):
         """Test that revision history is ordered by date, not parent order."""
-        r = self.open_repo('ooo_merge.git')
+        r = self._repo = open_repo('ooo_merge.git')
         history = r.revision_history(r.head())
         shas = [c.sha().hexdigest() for c in history]
         self.assertEqual(shas, ['7601d7f6231db6a57f7bbb79ee52e4d462fd44d1',
                                 'f507291b64138b875c28e03469025b1ea20bc614',
                                 'fb5b0425c7ce46959bec94d54b9a157645e114f5',
                                 'f9e39b120c68182a4ba35349f832d0e4e61f485c'])
-  
+
     def test_get_tags_empty(self):
-        r = self.open_repo('ooo_merge.git')
-        self.assertEquals({}, r.refs.as_dict('refs/tags'))
+        r = self._repo = open_repo('ooo_merge.git')
+        self.assertEqual({}, r.refs.as_dict('refs/tags'))
+
+    def test_get_config(self):
+        r = self._repo = open_repo('ooo_merge.git')
+        self.assertEquals({}, r.get_config())
+
+    def test_common_revisions(self):
+        """
+        This test demonstrates that ``find_common_revisions()`` actually returns
+        common heads, not revisions; dulwich already uses
+        ``find_common_revisions()`` in such a manner (see
+        ``Repo.fetch_objects()``).
+        """
+
+        expected_shas = set(['60dacdc733de308bb77bb76ce0fb0f9b44c9769e'])
+
+        # Source for objects.
+        r_base = open_repo('simple_merge.git')
+
+        # Re-create each-side of the merge in simple_merge.git.
+        #
+        # Since the trees and blobs are missing, the repository created is
+        # corrupted, but we're only checking for commits for the purpose of this
+        # test, so it's immaterial.
+        r1_dir = tempfile.mkdtemp()
+        r1_commits = ['ab64bbdcc51b170d21588e5c5d391ee5c0c96dfd', # HEAD
+                      '60dacdc733de308bb77bb76ce0fb0f9b44c9769e',
+                      '0d89f20333fbb1d2f3a94da77f4981373d8f4310']
+
+        r2_dir = tempfile.mkdtemp()
+        r2_commits = ['4cffe90e0a41ad3f5190079d7c8f036bde29cbe6', # HEAD
+                      '60dacdc733de308bb77bb76ce0fb0f9b44c9769e',
+                      '0d89f20333fbb1d2f3a94da77f4981373d8f4310']
+
+        try:
+            r1 = Repo.init_bare(r1_dir)
+            map(lambda c: r1.object_store.add_object(r_base.get_object(c)), \
+                r1_commits)
+            r1.refs['HEAD'] = r1_commits[0]
+
+            r2 = Repo.init_bare(r2_dir)
+            map(lambda c: r2.object_store.add_object(r_base.get_object(c)), \
+                r2_commits)
+            r2.refs['HEAD'] = r2_commits[0]
+
+            # Finally, the 'real' testing!
+            shas = r2.object_store.find_common_revisions(r1.get_graph_walker())
+            self.assertEqual(set(shas), expected_shas)
+
+            shas = r1.object_store.find_common_revisions(r2.get_graph_walker())
+            self.assertEqual(set(shas), expected_shas)
+        finally:
+            shutil.rmtree(r1_dir)
+            shutil.rmtree(r2_dir)
+
+
+class BuildRepoTests(TestCase):
+    """Tests that build on-disk repos from scratch.
+
+    Repos live in a temp dir and are torn down after each test. They start with
+    a single commit in master having single file named 'a'.
+    """
+
+    def setUp(self):
+        super(BuildRepoTests, self).setUp()
+        repo_dir = os.path.join(tempfile.mkdtemp(), 'test')
+        os.makedirs(repo_dir)
+        r = self._repo = Repo.init(repo_dir)
+        self.assertFalse(r.bare)
+        self.assertEqual('ref: refs/heads/master', r.refs.read_ref('HEAD'))
+        self.assertRaises(KeyError, lambda: r.refs['refs/heads/master'])
+
+        f = open(os.path.join(r.path, 'a'), 'wb')
+        try:
+            f.write('file contents')
+        finally:
+            f.close()
+        r.stage(['a'])
+        commit_sha = r.do_commit('msg',
+                                 committer='Test Committer <test@xxxxxxxxxxxx>',
+                                 author='Test Author <test@xxxxxxxxxxxx>',
+                                 commit_timestamp=12345, commit_timezone=0,
+                                 author_timestamp=12345, author_timezone=0)
+        self.assertEqual([], r[commit_sha].parents)
+        self._root_commit = commit_sha
+
+    def tearDown(self):
+        tear_down_repo(self._repo)
+        super(BuildRepoTests, self).tearDown()
+
+    def test_build_repo(self):
+        r = self._repo
+        self.assertEqual('ref: refs/heads/master', r.refs.read_ref('HEAD'))
+        self.assertEqual(self._root_commit, r.refs['refs/heads/master'])
+        expected_blob = objects.Blob.from_string('file contents')
+        self.assertEqual(expected_blob.data, r[expected_blob.id].data)
+        actual_commit = r[self._root_commit]
+        self.assertEqual('msg', actual_commit.message)
+
+    def test_commit_modified(self):
+        r = self._repo
+        f = open(os.path.join(r.path, 'a'), 'wb')
+        try:
+            f.write('new contents')
+        finally:
+            f.close()
+        r.stage(['a'])
+        commit_sha = r.do_commit('modified a',
+                                 committer='Test Committer <test@xxxxxxxxxxxx>',
+                                 author='Test Author <test@xxxxxxxxxxxx>',
+                                 commit_timestamp=12395, commit_timezone=0,
+                                 author_timestamp=12395, author_timezone=0)
+        self.assertEqual([self._root_commit], r[commit_sha].parents)
+        _, blob_id = tree_lookup_path(r.get_object, r[commit_sha].tree, 'a')
+        self.assertEqual('new contents', r[blob_id].data)
+
+    def test_commit_deleted(self):
+        r = self._repo
+        os.remove(os.path.join(r.path, 'a'))
+        r.stage(['a'])
+        commit_sha = r.do_commit('deleted a',
+                                 committer='Test Committer <test@xxxxxxxxxxxx>',
+                                 author='Test Author <test@xxxxxxxxxxxx>',
+                                 commit_timestamp=12395, commit_timezone=0,
+                                 author_timestamp=12395, author_timezone=0)
+        self.assertEqual([self._root_commit], r[commit_sha].parents)
+        self.assertEqual([], list(r.open_index()))
+        tree = r[r[commit_sha].tree]
+        self.assertEqual([], list(tree.iteritems()))
+
+    def test_commit_encoding(self):
+        r = self._repo
+        commit_sha = r.do_commit('commit with strange character \xee',
+             committer='Test Committer <test@xxxxxxxxxxxx>',
+             author='Test Author <test@xxxxxxxxxxxx>',
+             commit_timestamp=12395, commit_timezone=0,
+             author_timestamp=12395, author_timezone=0,
+             encoding="iso8859-1")
+        self.assertEquals("iso8859-1", r[commit_sha].encoding)
+
+    def test_commit_fail_ref(self):
+        r = self._repo
+
+        def set_if_equals(name, old_ref, new_ref):
+            return False
+        r.refs.set_if_equals = set_if_equals
+
+        def add_if_new(name, new_ref):
+            self.fail('Unexpected call to add_if_new')
+        r.refs.add_if_new = add_if_new
+
+        old_shas = set(r.object_store)
+        self.assertRaises(errors.CommitError, r.do_commit, 'failed commit',
+                          committer='Test Committer <test@xxxxxxxxxxxx>',
+                          author='Test Author <test@xxxxxxxxxxxx>',
+                          commit_timestamp=12345, commit_timezone=0,
+                          author_timestamp=12345, author_timezone=0)
+        new_shas = set(r.object_store) - old_shas
+        self.assertEqual(1, len(new_shas))
+        # Check that the new commit (now garbage) was added.
+        new_commit = r[new_shas.pop()]
+        self.assertEqual(r[self._root_commit].tree, new_commit.tree)
+        self.assertEqual('failed commit', new_commit.message)
+
+    def test_stage_deleted(self):
+        r = self._repo
+        os.remove(os.path.join(r.path, 'a'))
+        r.stage(['a'])
+        r.stage(['a'])  # double-stage a deleted path
+
+
+class CheckRefFormatTests(TestCase):
+    """Tests for the check_ref_format function.
+
+    These are the same tests as in the git test suite.
+    """
+
+    def test_valid(self):
+        self.assertTrue(check_ref_format('heads/foo'))
+        self.assertTrue(check_ref_format('foo/bar/baz'))
+        self.assertTrue(check_ref_format('refs///heads/foo'))
+        self.assertTrue(check_ref_format('foo./bar'))
+        self.assertTrue(check_ref_format('heads/foo@bar'))
+        self.assertTrue(check_ref_format('heads/fix.lock.error'))
+
+    def test_invalid(self):
+        self.assertFalse(check_ref_format('foo'))
+        self.assertFalse(check_ref_format('heads/foo/'))
+        self.assertFalse(check_ref_format('./foo'))
+        self.assertFalse(check_ref_format('.refs/foo'))
+        self.assertFalse(check_ref_format('heads/foo..bar'))
+        self.assertFalse(check_ref_format('heads/foo?bar'))
+        self.assertFalse(check_ref_format('heads/foo.lock'))
+        self.assertFalse(check_ref_format('heads/v@{ation'))
+        self.assertFalse(check_ref_format('heads/foo\bar'))
+
+
+ONES = "1" * 40
+TWOS = "2" * 40
+THREES = "3" * 40
+FOURS = "4" * 40
+
+class PackedRefsFileTests(TestCase):
+
+    def test_split_ref_line_errors(self):
+        self.assertRaises(errors.PackedRefsException, _split_ref_line,
+                          'singlefield')
+        self.assertRaises(errors.PackedRefsException, _split_ref_line,
+                          'badsha name')
+        self.assertRaises(errors.PackedRefsException, _split_ref_line,
+                          '%s bad/../refname' % ONES)
+
+    def test_read_without_peeled(self):
+        f = StringIO('# comment\n%s ref/1\n%s ref/2' % (ONES, TWOS))
+        self.assertEqual([(ONES, 'ref/1'), (TWOS, 'ref/2')],
+                         list(read_packed_refs(f)))
+
+    def test_read_without_peeled_errors(self):
+        f = StringIO('%s ref/1\n^%s' % (ONES, TWOS))
+        self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
+
+    def test_read_with_peeled(self):
+        f = StringIO('%s ref/1\n%s ref/2\n^%s\n%s ref/4' % (
+          ONES, TWOS, THREES, FOURS))
+        self.assertEqual([
+          (ONES, 'ref/1', None),
+          (TWOS, 'ref/2', THREES),
+          (FOURS, 'ref/4', None),
+          ], list(read_packed_refs_with_peeled(f)))
+
+    def test_read_with_peeled_errors(self):
+        f = StringIO('^%s\n%s ref/1' % (TWOS, ONES))
+        self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
+
+        f = StringIO('%s ref/1\n^%s\n^%s' % (ONES, TWOS, THREES))
+        self.assertRaises(errors.PackedRefsException, list, read_packed_refs(f))
+
+    def test_write_with_peeled(self):
+        f = StringIO()
+        write_packed_refs(f, {'ref/1': ONES, 'ref/2': TWOS},
+                          {'ref/1': THREES})
+        self.assertEqual(
+          "# pack-refs with: peeled\n%s ref/1\n^%s\n%s ref/2\n" % (
+          ONES, THREES, TWOS), f.getvalue())
+
+    def test_write_without_peeled(self):
+        f = StringIO()
+        write_packed_refs(f, {'ref/1': ONES, 'ref/2': TWOS})
+        self.assertEqual("%s ref/1\n%s ref/2\n" % (ONES, TWOS), f.getvalue())
+
+
+# Dict of refs that we expect all RefsContainerTests subclasses to define.
+_TEST_REFS = {
+  'HEAD': '42d06bd4b77fed026b154d16493e5deab78f02ec',
+  'refs/heads/master': '42d06bd4b77fed026b154d16493e5deab78f02ec',
+  'refs/heads/packed': '42d06bd4b77fed026b154d16493e5deab78f02ec',
+  'refs/tags/refs-0.1': 'df6800012397fb85c56e7418dd4eb9405dee075c',
+  'refs/tags/refs-0.2': '3ec9c43c84ff242e3ef4a9fc5bc111fd780a76a8',
+  }
+
+
+class RefsContainerTests(object):
+
+    def test_keys(self):
+        actual_keys = set(self._refs.keys())
+        self.assertEqual(set(self._refs.allkeys()), actual_keys)
+        # ignore the symref loop if it exists
+        actual_keys.discard('refs/heads/loop')
+        self.assertEqual(set(_TEST_REFS.iterkeys()), actual_keys)
+
+        actual_keys = self._refs.keys('refs/heads')
+        actual_keys.discard('loop')
+        self.assertEqual(['master', 'packed'], sorted(actual_keys))
+        self.assertEqual(['refs-0.1', 'refs-0.2'],
+                         sorted(self._refs.keys('refs/tags')))
+
+    def test_as_dict(self):
+        # refs/heads/loop does not show up even if it exists
+        self.assertEqual(_TEST_REFS, self._refs.as_dict())
+
+    def test_setitem(self):
+        self._refs['refs/some/ref'] = '42d06bd4b77fed026b154d16493e5deab78f02ec'
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs['refs/some/ref'])
+        self.assertRaises(errors.RefFormatError, self._refs.__setitem__,
+                          'notrefs/foo', '42d06bd4b77fed026b154d16493e5deab78f02ec')
+
+    def test_set_if_equals(self):
+        nines = '9' * 40
+        self.assertFalse(self._refs.set_if_equals('HEAD', 'c0ffee', nines))
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs['HEAD'])
+
+        self.assertTrue(self._refs.set_if_equals(
+          'HEAD', '42d06bd4b77fed026b154d16493e5deab78f02ec', nines))
+        self.assertEqual(nines, self._refs['HEAD'])
+
+        self.assertTrue(self._refs.set_if_equals('refs/heads/master', None,
+                                                 nines))
+        self.assertEqual(nines, self._refs['refs/heads/master'])
+
+    def test_add_if_new(self):
+        nines = '9' * 40
+        self.assertFalse(self._refs.add_if_new('refs/heads/master', nines))
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs['refs/heads/master'])
+
+        self.assertTrue(self._refs.add_if_new('refs/some/ref', nines))
+        self.assertEqual(nines, self._refs['refs/some/ref'])
+
+    def test_set_symbolic_ref(self):
+        self._refs.set_symbolic_ref('refs/heads/symbolic', 'refs/heads/master')
+        self.assertEqual('ref: refs/heads/master',
+                         self._refs.read_loose_ref('refs/heads/symbolic'))
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs['refs/heads/symbolic'])
+
+    def test_set_symbolic_ref_overwrite(self):
+        nines = '9' * 40
+        self.assertFalse('refs/heads/symbolic' in self._refs)
+        self._refs['refs/heads/symbolic'] = nines
+        self.assertEqual(nines, self._refs.read_loose_ref('refs/heads/symbolic'))
+        self._refs.set_symbolic_ref('refs/heads/symbolic', 'refs/heads/master')
+        self.assertEqual('ref: refs/heads/master',
+                         self._refs.read_loose_ref('refs/heads/symbolic'))
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs['refs/heads/symbolic'])
+
+    def test_check_refname(self):
+        self._refs._check_refname('HEAD')
+        self._refs._check_refname('refs/heads/foo')
+
+        self.assertRaises(errors.RefFormatError, self._refs._check_refname,
+                          'refs')
+        self.assertRaises(errors.RefFormatError, self._refs._check_refname,
+                          'notrefs/foo')
+
+    def test_contains(self):
+        self.assertTrue('refs/heads/master' in self._refs)
+        self.assertFalse('refs/heads/bar' in self._refs)
+
+    def test_delitem(self):
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                          self._refs['refs/heads/master'])
+        del self._refs['refs/heads/master']
+        self.assertRaises(KeyError, lambda: self._refs['refs/heads/master'])
+
+    def test_remove_if_equals(self):
+        self.assertFalse(self._refs.remove_if_equals('HEAD', 'c0ffee'))
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs['HEAD'])
+        self.assertTrue(self._refs.remove_if_equals(
+          'refs/tags/refs-0.2', '3ec9c43c84ff242e3ef4a9fc5bc111fd780a76a8'))
+        self.assertFalse('refs/tags/refs-0.2' in self._refs)
+
+
+class DictRefsContainerTests(RefsContainerTests, TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self._refs = DictRefsContainer(dict(_TEST_REFS))
+
+    def test_invalid_refname(self):
+        # FIXME: Move this test into RefsContainerTests, but requires
+        # some way of injecting invalid refs.
+        self._refs._refs["refs/stash"] = "00" * 20
+        expected_refs = dict(_TEST_REFS)
+        expected_refs["refs/stash"] = "00" * 20
+        self.assertEquals(expected_refs, self._refs.as_dict())
+
+
+class DiskRefsContainerTests(RefsContainerTests, TestCase):
+
+    def setUp(self):
+        TestCase.setUp(self)
+        self._repo = open_repo('refs.git')
+        self._refs = self._repo.refs
+
+    def tearDown(self):
+        tear_down_repo(self._repo)
+        TestCase.tearDown(self)
+
+    def test_get_packed_refs(self):
+        self.assertEqual({
+          'refs/heads/packed': '42d06bd4b77fed026b154d16493e5deab78f02ec',
+          'refs/tags/refs-0.1': 'df6800012397fb85c56e7418dd4eb9405dee075c',
+          }, self._refs.get_packed_refs())
+
+    def test_get_peeled_not_packed(self):
+        # not packed
+        self.assertEqual(None, self._refs.get_peeled('refs/tags/refs-0.2'))
+        self.assertEqual('3ec9c43c84ff242e3ef4a9fc5bc111fd780a76a8',
+                         self._refs['refs/tags/refs-0.2'])
+
+        # packed, known not peelable
+        self.assertEqual(self._refs['refs/heads/packed'],
+                         self._refs.get_peeled('refs/heads/packed'))
+
+        # packed, peeled
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs.get_peeled('refs/tags/refs-0.1'))
+
+    def test_setitem(self):
+        RefsContainerTests.test_setitem(self)
+        f = open(os.path.join(self._refs.path, 'refs', 'some', 'ref'), 'rb')
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                          f.read()[:40])
+        f.close()
+
+    def test_setitem_symbolic(self):
+        ones = '1' * 40
+        self._refs['HEAD'] = ones
+        self.assertEqual(ones, self._refs['HEAD'])
+
+        # ensure HEAD was not modified
+        f = open(os.path.join(self._refs.path, 'HEAD'), 'rb')
+        self.assertEqual('ref: refs/heads/master', iter(f).next().rstrip('\n'))
+        f.close()
+
+        # ensure the symbolic link was written through
+        f = open(os.path.join(self._refs.path, 'refs', 'heads', 'master'), 'rb')
+        self.assertEqual(ones, f.read()[:40])
+        f.close()
+
+    def test_set_if_equals(self):
+        RefsContainerTests.test_set_if_equals(self)
+
+        # ensure symref was followed
+        self.assertEqual('9' * 40, self._refs['refs/heads/master'])
+
+        # ensure lockfile was deleted
+        self.assertFalse(os.path.exists(
+          os.path.join(self._refs.path, 'refs', 'heads', 'master.lock')))
+        self.assertFalse(os.path.exists(
+          os.path.join(self._refs.path, 'HEAD.lock')))
+
+    def test_add_if_new_packed(self):
+        # don't overwrite packed ref
+        self.assertFalse(self._refs.add_if_new('refs/tags/refs-0.1', '9' * 40))
+        self.assertEqual('df6800012397fb85c56e7418dd4eb9405dee075c',
+                         self._refs['refs/tags/refs-0.1'])
+
+    def test_add_if_new_symbolic(self):
+        # Use an empty repo instead of the default.
+        tear_down_repo(self._repo)
+        repo_dir = os.path.join(tempfile.mkdtemp(), 'test')
+        os.makedirs(repo_dir)
+        self._repo = Repo.init(repo_dir)
+        refs = self._repo.refs
+
+        nines = '9' * 40
+        self.assertEqual('ref: refs/heads/master', refs.read_ref('HEAD'))
+        self.assertFalse('refs/heads/master' in refs)
+        self.assertTrue(refs.add_if_new('HEAD', nines))
+        self.assertEqual('ref: refs/heads/master', refs.read_ref('HEAD'))
+        self.assertEqual(nines, refs['HEAD'])
+        self.assertEqual(nines, refs['refs/heads/master'])
+        self.assertFalse(refs.add_if_new('HEAD', '1' * 40))
+        self.assertEqual(nines, refs['HEAD'])
+        self.assertEqual(nines, refs['refs/heads/master'])
+
+    def test_follow(self):
+        self.assertEquals(
+          ('refs/heads/master', '42d06bd4b77fed026b154d16493e5deab78f02ec'),
+          self._refs._follow('HEAD'))
+        self.assertEquals(
+          ('refs/heads/master', '42d06bd4b77fed026b154d16493e5deab78f02ec'),
+          self._refs._follow('refs/heads/master'))
+        self.assertRaises(KeyError, self._refs._follow, 'refs/heads/loop')
+
+    def test_delitem(self):
+        RefsContainerTests.test_delitem(self)
+        ref_file = os.path.join(self._refs.path, 'refs', 'heads', 'master')
+        self.assertFalse(os.path.exists(ref_file))
+        self.assertFalse('refs/heads/master' in self._refs.get_packed_refs())
+
+    def test_delitem_symbolic(self):
+        self.assertEqual('ref: refs/heads/master',
+                          self._refs.read_loose_ref('HEAD'))
+        del self._refs['HEAD']
+        self.assertRaises(KeyError, lambda: self._refs['HEAD'])
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+                         self._refs['refs/heads/master'])
+        self.assertFalse(os.path.exists(os.path.join(self._refs.path, 'HEAD')))
+
+    def test_remove_if_equals_symref(self):
+        # HEAD is a symref, so shouldn't equal its dereferenced value
+        self.assertFalse(self._refs.remove_if_equals(
+          'HEAD', '42d06bd4b77fed026b154d16493e5deab78f02ec'))
+        self.assertTrue(self._refs.remove_if_equals(
+          'refs/heads/master', '42d06bd4b77fed026b154d16493e5deab78f02ec'))
+        self.assertRaises(KeyError, lambda: self._refs['refs/heads/master'])
+
+        # HEAD is now a broken symref
+        self.assertRaises(KeyError, lambda: self._refs['HEAD'])
+        self.assertEqual('ref: refs/heads/master',
+                          self._refs.read_loose_ref('HEAD'))
+
+        self.assertFalse(os.path.exists(
+            os.path.join(self._refs.path, 'refs', 'heads', 'master.lock')))
+        self.assertFalse(os.path.exists(
+            os.path.join(self._refs.path, 'HEAD.lock')))
+
+    def test_remove_packed_without_peeled(self):
+        refs_file = os.path.join(self._repo.path, 'packed-refs')
+        f = GitFile(refs_file)
+        refs_data = f.read()
+        f.close()
+        f = GitFile(refs_file, 'wb')
+        f.write('\n'.join(l for l in refs_data.split('\n')
+                          if not l or l[0] not in '#^'))
+        f.close()
+        self._repo = Repo(self._repo.path)
+        refs = self._repo.refs
+        self.assertTrue(refs.remove_if_equals(
+          'refs/heads/packed', '42d06bd4b77fed026b154d16493e5deab78f02ec'))
+
+    def test_remove_if_equals_packed(self):
+        # test removing ref that is only packed
+        self.assertEqual('df6800012397fb85c56e7418dd4eb9405dee075c',
+                         self._refs['refs/tags/refs-0.1'])
+        self.assertTrue(
+          self._refs.remove_if_equals('refs/tags/refs-0.1',
+          'df6800012397fb85c56e7418dd4eb9405dee075c'))
+        self.assertRaises(KeyError, lambda: self._refs['refs/tags/refs-0.1'])
+
+    def test_read_ref(self):
+        self.assertEqual('ref: refs/heads/master', self._refs.read_ref("HEAD"))
+        self.assertEqual('42d06bd4b77fed026b154d16493e5deab78f02ec',
+            self._refs.read_ref("refs/heads/packed"))
+        self.assertEqual(None,
+            self._refs.read_ref("nonexistant"))

=== added file 'dulwich/tests/test_server.py'
--- dulwich/tests/test_server.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/test_server.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,695 @@
+# test_server.py -- Tests for the git server
+# Copyright (C) 2010 Google, Inc.
+#
+# 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
+# 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.
+
+"""Tests for the smart protocol server."""
+
+from cStringIO import StringIO
+import os
+import tempfile
+
+from dulwich.errors import (
+    GitProtocolError,
+    NotGitRepository,
+    UnexpectedCommandError,
+    )
+from dulwich.repo import (
+    MemoryRepo,
+    Repo,
+    )
+from dulwich.server import (
+    Backend,
+    DictBackend,
+    FileSystemBackend,
+    Handler,
+    MultiAckGraphWalkerImpl,
+    MultiAckDetailedGraphWalkerImpl,
+    _split_proto_line,
+    serve_command,
+    ProtocolGraphWalker,
+    ReceivePackHandler,
+    SingleAckGraphWalkerImpl,
+    UploadPackHandler,
+    )
+from dulwich.tests import TestCase
+from dulwich.tests.utils import (
+    make_commit,
+    )
+
+
+ONE = '1' * 40
+TWO = '2' * 40
+THREE = '3' * 40
+FOUR = '4' * 40
+FIVE = '5' * 40
+SIX = '6' * 40
+
+
+class TestProto(object):
+
+    def __init__(self):
+        self._output = []
+        self._received = {0: [], 1: [], 2: [], 3: []}
+
+    def set_output(self, output_lines):
+        self._output = ['%s\n' % line.rstrip() for line in output_lines]
+
+    def read_pkt_line(self):
+        if self._output:
+            return self._output.pop(0)
+        else:
+            return None
+
+    def write_sideband(self, band, data):
+        self._received[band].append(data)
+
+    def write_pkt_line(self, data):
+        if data is None:
+            data = 'None'
+        self._received[0].append(data)
+
+    def get_received_line(self, band=0):
+        lines = self._received[band]
+        if lines:
+            return lines.pop(0)
+        else:
+            return None
+
+
+class TestGenericHandler(Handler):
+
+    def __init__(self):
+        Handler.__init__(self, Backend(), None)
+
+    @classmethod
+    def capabilities(cls):
+        return ('cap1', 'cap2', 'cap3')
+
+    @classmethod
+    def required_capabilities(cls):
+        return ('cap2',)
+
+
+class HandlerTestCase(TestCase):
+
+    def setUp(self):
+        super(HandlerTestCase, self).setUp()
+        self._handler = TestGenericHandler()
+
+    def assertSucceeds(self, func, *args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except GitProtocolError, e:
+            self.fail(e)
+
+    def test_capability_line(self):
+        self.assertEquals('cap1 cap2 cap3', self._handler.capability_line())
+
+    def test_set_client_capabilities(self):
+        set_caps = self._handler.set_client_capabilities
+        self.assertSucceeds(set_caps, ['cap2'])
+        self.assertSucceeds(set_caps, ['cap1', 'cap2'])
+
+        # different order
+        self.assertSucceeds(set_caps, ['cap3', 'cap1', 'cap2'])
+
+        # error cases
+        self.assertRaises(GitProtocolError, set_caps, ['capxxx', 'cap2'])
+        self.assertRaises(GitProtocolError, set_caps, ['cap1', 'cap3'])
+
+        # ignore innocuous but unknown capabilities
+        self.assertRaises(GitProtocolError, set_caps, ['cap2', 'ignoreme'])
+        self.assertFalse('ignoreme' in self._handler.capabilities())
+        self._handler.innocuous_capabilities = lambda: ('ignoreme',)
+        self.assertSucceeds(set_caps, ['cap2', 'ignoreme'])
+
+    def test_has_capability(self):
+        self.assertRaises(GitProtocolError, self._handler.has_capability, 'cap')
+        caps = self._handler.capabilities()
+        self._handler.set_client_capabilities(caps)
+        for cap in caps:
+            self.assertTrue(self._handler.has_capability(cap))
+        self.assertFalse(self._handler.has_capability('capxxx'))
+
+
+class UploadPackHandlerTestCase(TestCase):
+
+    def setUp(self):
+        super(UploadPackHandlerTestCase, self).setUp()
+        self._repo = MemoryRepo.init_bare([], {})
+        backend = DictBackend({'/': self._repo})
+        self._handler = UploadPackHandler(
+          backend, ['/', 'host=lolcathost'], TestProto())
+
+    def test_progress(self):
+        caps = self._handler.required_capabilities()
+        self._handler.set_client_capabilities(caps)
+        self._handler.progress('first message')
+        self._handler.progress('second message')
+        self.assertEqual('first message',
+                         self._handler.proto.get_received_line(2))
+        self.assertEqual('second message',
+                         self._handler.proto.get_received_line(2))
+        self.assertEqual(None, self._handler.proto.get_received_line(2))
+
+    def test_no_progress(self):
+        caps = list(self._handler.required_capabilities()) + ['no-progress']
+        self._handler.set_client_capabilities(caps)
+        self._handler.progress('first message')
+        self._handler.progress('second message')
+        self.assertEqual(None, self._handler.proto.get_received_line(2))
+
+    def test_get_tagged(self):
+        refs = {
+            'refs/tags/tag1': ONE,
+            'refs/tags/tag2': TWO,
+            'refs/heads/master': FOUR,  # not a tag, no peeled value
+            }
+        # repo needs to peel this object
+        self._repo.object_store.add_object(make_commit(id=FOUR))
+        self._repo.refs._update(refs)
+        peeled = {
+            'refs/tags/tag1': '1234' * 10,
+            'refs/tags/tag2': '5678' * 10,
+            }
+        self._repo.refs._update_peeled(peeled)
+
+        caps = list(self._handler.required_capabilities()) + ['include-tag']
+        self._handler.set_client_capabilities(caps)
+        self.assertEquals({'1234' * 10: ONE, '5678' * 10: TWO},
+                          self._handler.get_tagged(refs, repo=self._repo))
+
+        # non-include-tag case
+        caps = self._handler.required_capabilities()
+        self._handler.set_client_capabilities(caps)
+        self.assertEquals({}, self._handler.get_tagged(refs, repo=self._repo))
+
+
+class TestUploadPackHandler(UploadPackHandler):
+    @classmethod
+    def required_capabilities(self):
+        return ()
+
+
+class ProtocolGraphWalkerTestCase(TestCase):
+
+    def setUp(self):
+        super(ProtocolGraphWalkerTestCase, self).setUp()
+        # Create the following commit tree:
+        #   3---5
+        #  /
+        # 1---2---4
+        commits = [
+          make_commit(id=ONE, parents=[], commit_time=111),
+          make_commit(id=TWO, parents=[ONE], commit_time=222),
+          make_commit(id=THREE, parents=[ONE], commit_time=333),
+          make_commit(id=FOUR, parents=[TWO], commit_time=444),
+          make_commit(id=FIVE, parents=[THREE], commit_time=555),
+          ]
+        self._repo = MemoryRepo.init_bare(commits, {})
+        backend = DictBackend({'/': self._repo})
+        self._walker = ProtocolGraphWalker(
+            TestUploadPackHandler(backend, ['/', 'host=lolcats'], TestProto()),
+            self._repo.object_store, self._repo.get_peeled)
+
+    def test_is_satisfied_no_haves(self):
+        self.assertFalse(self._walker._is_satisfied([], ONE, 0))
+        self.assertFalse(self._walker._is_satisfied([], TWO, 0))
+        self.assertFalse(self._walker._is_satisfied([], THREE, 0))
+
+    def test_is_satisfied_have_root(self):
+        self.assertTrue(self._walker._is_satisfied([ONE], ONE, 0))
+        self.assertTrue(self._walker._is_satisfied([ONE], TWO, 0))
+        self.assertTrue(self._walker._is_satisfied([ONE], THREE, 0))
+
+    def test_is_satisfied_have_branch(self):
+        self.assertTrue(self._walker._is_satisfied([TWO], TWO, 0))
+        # wrong branch
+        self.assertFalse(self._walker._is_satisfied([TWO], THREE, 0))
+
+    def test_all_wants_satisfied(self):
+        self._walker.set_wants([FOUR, FIVE])
+        # trivial case: wants == haves
+        self.assertTrue(self._walker.all_wants_satisfied([FOUR, FIVE]))
+        # cases that require walking the commit tree
+        self.assertTrue(self._walker.all_wants_satisfied([ONE]))
+        self.assertFalse(self._walker.all_wants_satisfied([TWO]))
+        self.assertFalse(self._walker.all_wants_satisfied([THREE]))
+        self.assertTrue(self._walker.all_wants_satisfied([TWO, THREE]))
+
+    def test_split_proto_line(self):
+        allowed = ('want', 'done', None)
+        self.assertEquals(('want', ONE),
+                          _split_proto_line('want %s\n' % ONE, allowed))
+        self.assertEquals(('want', TWO),
+                          _split_proto_line('want %s\n' % TWO, allowed))
+        self.assertRaises(GitProtocolError, _split_proto_line,
+                          'want xxxx\n', allowed)
+        self.assertRaises(UnexpectedCommandError, _split_proto_line,
+                          'have %s\n' % THREE, allowed)
+        self.assertRaises(GitProtocolError, _split_proto_line,
+                          'foo %s\n' % FOUR, allowed)
+        self.assertRaises(GitProtocolError, _split_proto_line, 'bar', allowed)
+        self.assertEquals(('done', None), _split_proto_line('done\n', allowed))
+        self.assertEquals((None, None), _split_proto_line('', allowed))
+
+    def test_determine_wants(self):
+        self.assertRaises(GitProtocolError, self._walker.determine_wants, {})
+
+        self._walker.proto.set_output([
+          'want %s multi_ack' % ONE,
+          'want %s' % TWO,
+          ])
+        heads = {
+          'refs/heads/ref1': ONE,
+          'refs/heads/ref2': TWO,
+          'refs/heads/ref3': THREE,
+          }
+        self._repo.refs._update(heads)
+        self.assertEquals([ONE, TWO], self._walker.determine_wants(heads))
+
+        self._walker.proto.set_output(['want %s multi_ack' % FOUR])
+        self.assertRaises(GitProtocolError, self._walker.determine_wants, heads)
+
+        self._walker.proto.set_output([])
+        self.assertEquals([], self._walker.determine_wants(heads))
+
+        self._walker.proto.set_output(['want %s multi_ack' % ONE, 'foo'])
+        self.assertRaises(GitProtocolError, self._walker.determine_wants, heads)
+
+        self._walker.proto.set_output(['want %s multi_ack' % FOUR])
+        self.assertRaises(GitProtocolError, self._walker.determine_wants, heads)
+
+    def test_determine_wants_advertisement(self):
+        self._walker.proto.set_output([])
+        # advertise branch tips plus tag
+        heads = {
+          'refs/heads/ref4': FOUR,
+          'refs/heads/ref5': FIVE,
+          'refs/heads/tag6': SIX,
+          }
+        self._repo.refs._update(heads)
+        self._repo.refs._update_peeled(heads)
+        self._repo.refs._update_peeled({'refs/heads/tag6': FIVE})
+        self._walker.determine_wants(heads)
+        lines = []
+        while True:
+            line = self._walker.proto.get_received_line()
+            if line == 'None':
+                break
+            # strip capabilities list if present
+            if '\x00' in line:
+                line = line[:line.index('\x00')]
+            lines.append(line.rstrip())
+
+        self.assertEquals([
+          '%s refs/heads/ref4' % FOUR,
+          '%s refs/heads/ref5' % FIVE,
+          '%s refs/heads/tag6^{}' % FIVE,
+          '%s refs/heads/tag6' % SIX,
+          ], sorted(lines))
+
+        # ensure peeled tag was advertised immediately following tag
+        for i, line in enumerate(lines):
+            if line.endswith(' refs/heads/tag6'):
+                self.assertEquals('%s refs/heads/tag6^{}' % FIVE, lines[i+1])
+
+    # TODO: test commit time cutoff
+
+
+class TestProtocolGraphWalker(object):
+
+    def __init__(self):
+        self.acks = []
+        self.lines = []
+        self.done = False
+        self.stateless_rpc = False
+        self.advertise_refs = False
+
+    def read_proto_line(self, allowed):
+        command, sha = self.lines.pop(0)
+        if allowed is not None:
+            assert command in allowed
+        return command, sha
+
+    def send_ack(self, sha, ack_type=''):
+        self.acks.append((sha, ack_type))
+
+    def send_nak(self):
+        self.acks.append((None, 'nak'))
+
+    def all_wants_satisfied(self, haves):
+        return self.done
+
+    def pop_ack(self):
+        if not self.acks:
+            return None
+        return self.acks.pop(0)
+
+
+class AckGraphWalkerImplTestCase(TestCase):
+    """Base setup and asserts for AckGraphWalker tests."""
+
+    def setUp(self):
+        super(AckGraphWalkerImplTestCase, self).setUp()
+        self._walker = TestProtocolGraphWalker()
+        self._walker.lines = [
+          ('have', TWO),
+          ('have', ONE),
+          ('have', THREE),
+          ('done', None),
+          ]
+        self._impl = self.impl_cls(self._walker)
+
+    def assertNoAck(self):
+        self.assertEquals(None, self._walker.pop_ack())
+
+    def assertAcks(self, acks):
+        for sha, ack_type in acks:
+            self.assertEquals((sha, ack_type), self._walker.pop_ack())
+        self.assertNoAck()
+
+    def assertAck(self, sha, ack_type=''):
+        self.assertAcks([(sha, ack_type)])
+
+    def assertNak(self):
+        self.assertAck(None, 'nak')
+
+    def assertNextEquals(self, sha):
+        self.assertEquals(sha, self._impl.next())
+
+
+class SingleAckGraphWalkerImplTestCase(AckGraphWalkerImplTestCase):
+
+    impl_cls = SingleAckGraphWalkerImpl
+
+    def test_single_ack(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self._walker.done = True
+        self._impl.ack(ONE)
+        self.assertAck(ONE)
+
+        self.assertNextEquals(THREE)
+        self._impl.ack(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNoAck()
+
+    def test_single_ack_flush(self):
+        # same as ack test but ends with a flush-pkt instead of done
+        self._walker.lines[-1] = (None, None)
+
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self._walker.done = True
+        self._impl.ack(ONE)
+        self.assertAck(ONE)
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNoAck()
+
+    def test_single_ack_nak(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNoAck()
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNak()
+
+    def test_single_ack_nak_flush(self):
+        # same as nak test but ends with a flush-pkt instead of done
+        self._walker.lines[-1] = (None, None)
+
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNoAck()
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNak()
+
+
+class MultiAckGraphWalkerImplTestCase(AckGraphWalkerImplTestCase):
+
+    impl_cls = MultiAckGraphWalkerImpl
+
+    def test_multi_ack(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self._walker.done = True
+        self._impl.ack(ONE)
+        self.assertAck(ONE, 'continue')
+
+        self.assertNextEquals(THREE)
+        self._impl.ack(THREE)
+        self.assertAck(THREE, 'continue')
+
+        self.assertNextEquals(None)
+        self.assertAck(THREE)
+
+    def test_multi_ack_partial(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self._impl.ack(ONE)
+        self.assertAck(ONE, 'continue')
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        # done, re-send ack of last common
+        self.assertAck(ONE)
+
+    def test_multi_ack_flush(self):
+        self._walker.lines = [
+          ('have', TWO),
+          (None, None),
+          ('have', ONE),
+          ('have', THREE),
+          ('done', None),
+          ]
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNak()  # nak the flush-pkt
+
+        self._walker.done = True
+        self._impl.ack(ONE)
+        self.assertAck(ONE, 'continue')
+
+        self.assertNextEquals(THREE)
+        self._impl.ack(THREE)
+        self.assertAck(THREE, 'continue')
+
+        self.assertNextEquals(None)
+        self.assertAck(THREE)
+
+    def test_multi_ack_nak(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNoAck()
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNak()
+
+
+class MultiAckDetailedGraphWalkerImplTestCase(AckGraphWalkerImplTestCase):
+
+    impl_cls = MultiAckDetailedGraphWalkerImpl
+
+    def test_multi_ack(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self._walker.done = True
+        self._impl.ack(ONE)
+        self.assertAcks([(ONE, 'common'), (ONE, 'ready')])
+
+        self.assertNextEquals(THREE)
+        self._impl.ack(THREE)
+        self.assertAck(THREE, 'ready')
+
+        self.assertNextEquals(None)
+        self.assertAck(THREE)
+
+    def test_multi_ack_partial(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self._impl.ack(ONE)
+        self.assertAck(ONE, 'common')
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        # done, re-send ack of last common
+        self.assertAck(ONE)
+
+    def test_multi_ack_flush(self):
+        # same as ack test but contains a flush-pkt in the middle
+        self._walker.lines = [
+          ('have', TWO),
+          (None, None),
+          ('have', ONE),
+          ('have', THREE),
+          ('done', None),
+          ]
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNak()  # nak the flush-pkt
+
+        self._walker.done = True
+        self._impl.ack(ONE)
+        self.assertAcks([(ONE, 'common'), (ONE, 'ready')])
+
+        self.assertNextEquals(THREE)
+        self._impl.ack(THREE)
+        self.assertAck(THREE, 'ready')
+
+        self.assertNextEquals(None)
+        self.assertAck(THREE)
+
+    def test_multi_ack_nak(self):
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNoAck()
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNak()
+
+    def test_multi_ack_nak_flush(self):
+        # same as nak test but contains a flush-pkt in the middle
+        self._walker.lines = [
+          ('have', TWO),
+          (None, None),
+          ('have', ONE),
+          ('have', THREE),
+          ('done', None),
+          ]
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNak()
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNak()
+
+    def test_multi_ack_stateless(self):
+        # transmission ends with a flush-pkt
+        self._walker.lines[-1] = (None, None)
+        self._walker.stateless_rpc = True
+
+        self.assertNextEquals(TWO)
+        self.assertNoAck()
+
+        self.assertNextEquals(ONE)
+        self.assertNoAck()
+
+        self.assertNextEquals(THREE)
+        self.assertNoAck()
+
+        self.assertNextEquals(None)
+        self.assertNak()
+
+
+class FileSystemBackendTests(TestCase):
+    """Tests for FileSystemBackend."""
+
+    def setUp(self):
+        super(FileSystemBackendTests, self).setUp()
+        self.path = tempfile.mkdtemp()
+        self.repo = Repo.init(self.path)
+        self.backend = FileSystemBackend()
+
+    def test_nonexistant(self):
+        self.assertRaises(NotGitRepository,
+            self.backend.open_repository, "/does/not/exist/unless/foo")
+
+    def test_absolute(self):
+        repo = self.backend.open_repository(self.path)
+        self.assertEquals(repo.path, self.repo.path)
+
+    def test_child(self):
+        self.assertRaises(NotGitRepository,
+            self.backend.open_repository, os.path.join(self.path, "foo"))
+
+
+class ServeCommandTests(TestCase):
+    """Tests for serve_command."""
+
+    def setUp(self):
+        super(ServeCommandTests, self).setUp()
+        self.backend = DictBackend({})
+
+    def serve_command(self, handler_cls, args, inf, outf):
+        return serve_command(handler_cls, ["test"] + args, backend=self.backend,
+            inf=inf, outf=outf)
+
+    def test_receive_pack(self):
+        commit = make_commit(id=ONE, parents=[], commit_time=111)
+        self.backend.repos["/"] = MemoryRepo.init_bare(
+            [commit], {"refs/heads/master": commit.id})
+        outf = StringIO()
+        exitcode = self.serve_command(ReceivePackHandler, ["/"], StringIO("0000"), outf)
+        outlines = outf.getvalue().splitlines()
+        self.assertEquals(2, len(outlines))
+        self.assertEquals("1111111111111111111111111111111111111111 refs/heads/master",
+            outlines[0][4:].split("\x00")[0])
+        self.assertEquals("0000", outlines[-1])
+        self.assertEquals(0, exitcode)

=== added file 'dulwich/tests/test_web.py'
--- dulwich/tests/test_web.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/test_web.py	2011-01-14 18:33:07 +0000
@@ -0,0 +1,436 @@
+# test_web.py -- Tests for the git HTTP server
+# Copyright (C) 2010 Google, Inc.
+#
+# 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
+# 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.
+
+"""Tests for the Git HTTP server."""
+
+from cStringIO import StringIO
+import re
+
+from dulwich.object_store import (
+    MemoryObjectStore,
+    )
+from dulwich.objects import (
+    Blob,
+    Tag,
+    )
+from dulwich.repo import (
+    BaseRepo,
+    MemoryRepo,
+    )
+from dulwich.server import (
+    DictBackend,
+    )
+from dulwich.tests import (
+    TestCase,
+    )
+from dulwich.web import (
+    HTTP_OK,
+    HTTP_NOT_FOUND,
+    HTTP_FORBIDDEN,
+    HTTP_ERROR,
+    send_file,
+    get_text_file,
+    get_loose_object,
+    get_pack_file,
+    get_idx_file,
+    get_info_refs,
+    get_info_packs,
+    handle_service_request,
+    _LengthLimitedFile,
+    HTTPGitRequest,
+    HTTPGitApplication,
+    )
+
+from dulwich.tests.utils import (
+    make_object,
+    )
+
+
+class TestHTTPGitRequest(HTTPGitRequest):
+    """HTTPGitRequest with overridden methods to help test caching."""
+
+    def __init__(self, *args, **kwargs):
+        HTTPGitRequest.__init__(self, *args, **kwargs)
+        self.cached = None
+
+    def nocache(self):
+        self.cached = False
+
+    def cache_forever(self):
+        self.cached = True
+
+
+class WebTestCase(TestCase):
+    """Base TestCase with useful instance vars and utility functions."""
+
+    _req_class = TestHTTPGitRequest
+
+    def setUp(self):
+        super(WebTestCase, self).setUp()
+        self._environ = {}
+        self._req = self._req_class(self._environ, self._start_response,
+                                    handlers=self._handlers())
+        self._status = None
+        self._headers = []
+        self._output = StringIO()
+
+    def _start_response(self, status, headers):
+        self._status = status
+        self._headers = list(headers)
+        return self._output.write
+
+    def _handlers(self):
+        return None
+
+    def assertContentTypeEquals(self, expected):
+        self.assertTrue(('Content-Type', expected) in self._headers)
+
+
+def _test_backend(objects, refs=None, named_files=None):
+    if not refs:
+        refs = {}
+    if not named_files:
+        named_files = {}
+    repo = MemoryRepo.init_bare(objects, refs)
+    for path, contents in named_files.iteritems():
+        repo._put_named_file(path, contents)
+    return DictBackend({'/': repo})
+
+
+class DumbHandlersTestCase(WebTestCase):
+
+    def test_send_file_not_found(self):
+        list(send_file(self._req, None, 'text/plain'))
+        self.assertEquals(HTTP_NOT_FOUND, self._status)
+
+    def test_send_file(self):
+        f = StringIO('foobar')
+        output = ''.join(send_file(self._req, f, 'some/thing'))
+        self.assertEquals('foobar', output)
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('some/thing')
+        self.assertTrue(f.closed)
+
+    def test_send_file_buffered(self):
+        bufsize = 10240
+        xs = 'x' * bufsize
+        f = StringIO(2 * xs)
+        self.assertEquals([xs, xs],
+                          list(send_file(self._req, f, 'some/thing')))
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('some/thing')
+        self.assertTrue(f.closed)
+
+    def test_send_file_error(self):
+        class TestFile(object):
+            def __init__(self, exc_class):
+                self.closed = False
+                self._exc_class = exc_class
+
+            def read(self, size=-1):
+                raise self._exc_class()
+
+            def close(self):
+                self.closed = True
+
+        f = TestFile(IOError)
+        list(send_file(self._req, f, 'some/thing'))
+        self.assertEquals(HTTP_ERROR, self._status)
+        self.assertTrue(f.closed)
+        self.assertFalse(self._req.cached)
+
+        # non-IOErrors are reraised
+        f = TestFile(AttributeError)
+        self.assertRaises(AttributeError, list,
+                          send_file(self._req, f, 'some/thing'))
+        self.assertTrue(f.closed)
+        self.assertFalse(self._req.cached)
+
+    def test_get_text_file(self):
+        backend = _test_backend([], named_files={'description': 'foo'})
+        mat = re.search('.*', 'description')
+        output = ''.join(get_text_file(self._req, backend, mat))
+        self.assertEquals('foo', output)
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('text/plain')
+        self.assertFalse(self._req.cached)
+
+    def test_get_loose_object(self):
+        blob = make_object(Blob, data='foo')
+        backend = _test_backend([blob])
+        mat = re.search('^(..)(.{38})$', blob.id)
+        output = ''.join(get_loose_object(self._req, backend, mat))
+        self.assertEquals(blob.as_legacy_object(), output)
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('application/x-git-loose-object')
+        self.assertTrue(self._req.cached)
+
+    def test_get_loose_object_missing(self):
+        mat = re.search('^(..)(.{38})$', '1' * 40)
+        list(get_loose_object(self._req, _test_backend([]), mat))
+        self.assertEquals(HTTP_NOT_FOUND, self._status)
+
+    def test_get_loose_object_error(self):
+        blob = make_object(Blob, data='foo')
+        backend = _test_backend([blob])
+        mat = re.search('^(..)(.{38})$', blob.id)
+
+        def as_legacy_object_error():
+            raise IOError
+
+        blob.as_legacy_object = as_legacy_object_error
+        list(get_loose_object(self._req, backend, mat))
+        self.assertEquals(HTTP_ERROR, self._status)
+
+    def test_get_pack_file(self):
+        pack_name = 'objects/pack/pack-%s.pack' % ('1' * 40)
+        backend = _test_backend([], named_files={pack_name: 'pack contents'})
+        mat = re.search('.*', pack_name)
+        output = ''.join(get_pack_file(self._req, backend, mat))
+        self.assertEquals('pack contents', output)
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('application/x-git-packed-objects')
+        self.assertTrue(self._req.cached)
+
+    def test_get_idx_file(self):
+        idx_name = 'objects/pack/pack-%s.idx' % ('1' * 40)
+        backend = _test_backend([], named_files={idx_name: 'idx contents'})
+        mat = re.search('.*', idx_name)
+        output = ''.join(get_idx_file(self._req, backend, mat))
+        self.assertEquals('idx contents', output)
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('application/x-git-packed-objects-toc')
+        self.assertTrue(self._req.cached)
+
+    def test_get_info_refs(self):
+        self._environ['QUERY_STRING'] = ''
+
+        blob1 = make_object(Blob, data='1')
+        blob2 = make_object(Blob, data='2')
+        blob3 = make_object(Blob, data='3')
+
+        tag1 = make_object(Tag, name='tag-tag',
+                           tagger='Test <test@xxxxxxxxxxx>',
+                           tag_time=12345,
+                           tag_timezone=0,
+                           message='message',
+                           object=(Blob, blob2.id))
+
+        objects = [blob1, blob2, blob3, tag1]
+        refs = {
+          'HEAD': '000',
+          'refs/heads/master': blob1.id,
+          'refs/tags/tag-tag': tag1.id,
+          'refs/tags/blob-tag': blob3.id,
+          }
+        backend = _test_backend(objects, refs=refs)
+
+        mat = re.search('.*', '//info/refs')
+        self.assertEquals(['%s\trefs/heads/master\n' % blob1.id,
+                           '%s\trefs/tags/blob-tag\n' % blob3.id,
+                           '%s\trefs/tags/tag-tag\n' % tag1.id,
+                           '%s\trefs/tags/tag-tag^{}\n' % blob2.id],
+                          list(get_info_refs(self._req, backend, mat)))
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('text/plain')
+        self.assertFalse(self._req.cached)
+
+    def test_get_info_packs(self):
+        class TestPack(object):
+            def __init__(self, sha):
+                self._sha = sha
+
+            def name(self):
+                return self._sha
+
+        packs = [TestPack(str(i) * 40) for i in xrange(1, 4)]
+
+        class TestObjectStore(MemoryObjectStore):
+            # property must be overridden, can't be assigned
+            @property
+            def packs(self):
+                return packs
+
+        store = TestObjectStore()
+        repo = BaseRepo(store, None)
+        backend = DictBackend({'/': repo})
+        mat = re.search('.*', '//info/packs')
+        output = ''.join(get_info_packs(self._req, backend, mat))
+        expected = 'P pack-%s.pack\n' * 3
+        expected %= ('1' * 40, '2' * 40, '3' * 40)
+        self.assertEquals(expected, output)
+        self.assertEquals(HTTP_OK, self._status)
+        self.assertContentTypeEquals('text/plain')
+        self.assertFalse(self._req.cached)
+
+
+class SmartHandlersTestCase(WebTestCase):
+
+    class _TestUploadPackHandler(object):
+        def __init__(self, backend, args, proto, stateless_rpc=False,
+                     advertise_refs=False):
+            self.args = args
+            self.proto = proto
+            self.stateless_rpc = stateless_rpc
+            self.advertise_refs = advertise_refs
+
+        def handle(self):
+            self.proto.write('handled input: %s' % self.proto.recv(1024))
+
+    def _make_handler(self, *args, **kwargs):
+        self._handler = self._TestUploadPackHandler(*args, **kwargs)
+        return self._handler
+
+    def _handlers(self):
+        return {'git-upload-pack': self._make_handler}
+
+    def test_handle_service_request_unknown(self):
+        mat = re.search('.*', '/git-evil-handler')
+        list(handle_service_request(self._req, 'backend', mat))
+        self.assertEquals(HTTP_FORBIDDEN, self._status)
+        self.assertFalse(self._req.cached)
+
+    def _run_handle_service_request(self, content_length=None):
+        self._environ['wsgi.input'] = StringIO('foo')
+        if content_length is not None:
+            self._environ['CONTENT_LENGTH'] = content_length
+        mat = re.search('.*', '/git-upload-pack')
+        handler_output = ''.join(
+          handle_service_request(self._req, 'backend', mat))
+        write_output = self._output.getvalue()
+        # Ensure all output was written via the write callback.
+        self.assertEqual('', handler_output)
+        self.assertEqual('handled input: foo', write_output)
+        self.assertContentTypeEquals('application/x-git-upload-pack-response')
+        self.assertFalse(self._handler.advertise_refs)
+        self.assertTrue(self._handler.stateless_rpc)
+        self.assertFalse(self._req.cached)
+
+    def test_handle_service_request(self):
+        self._run_handle_service_request()
+
+    def test_handle_service_request_with_length(self):
+        self._run_handle_service_request(content_length='3')
+
+    def test_handle_service_request_empty_length(self):
+        self._run_handle_service_request(content_length='')
+
+    def test_get_info_refs_unknown(self):
+        self._environ['QUERY_STRING'] = 'service=git-evil-handler'
+        list(get_info_refs(self._req, 'backend', None))
+        self.assertEquals(HTTP_FORBIDDEN, self._status)
+        self.assertFalse(self._req.cached)
+
+    def test_get_info_refs(self):
+        self._environ['wsgi.input'] = StringIO('foo')
+        self._environ['QUERY_STRING'] = 'service=git-upload-pack'
+
+        mat = re.search('.*', '/git-upload-pack')
+        handler_output = ''.join(get_info_refs(self._req, 'backend', mat))
+        write_output = self._output.getvalue()
+        self.assertEquals(('001e# service=git-upload-pack\n'
+                           '0000'
+                           # input is ignored by the handler
+                           'handled input: '), write_output)
+        # Ensure all output was written via the write callback.
+        self.assertEquals('', handler_output)
+        self.assertTrue(self._handler.advertise_refs)
+        self.assertTrue(self._handler.stateless_rpc)
+        self.assertFalse(self._req.cached)
+
+
+class LengthLimitedFileTestCase(TestCase):
+    def test_no_cutoff(self):
+        f = _LengthLimitedFile(StringIO('foobar'), 1024)
+        self.assertEquals('foobar', f.read())
+
+    def test_cutoff(self):
+        f = _LengthLimitedFile(StringIO('foobar'), 3)
+        self.assertEquals('foo', f.read())
+        self.assertEquals('', f.read())
+
+    def test_multiple_reads(self):
+        f = _LengthLimitedFile(StringIO('foobar'), 3)
+        self.assertEquals('fo', f.read(2))
+        self.assertEquals('o', f.read(2))
+        self.assertEquals('', f.read())
+
+
+class HTTPGitRequestTestCase(WebTestCase):
+
+    # This class tests the contents of the actual cache headers
+    _req_class = HTTPGitRequest
+
+    def test_not_found(self):
+        self._req.cache_forever()  # cache headers should be discarded
+        message = 'Something not found'
+        self.assertEquals(message, self._req.not_found(message))
+        self.assertEquals(HTTP_NOT_FOUND, self._status)
+        self.assertEquals(set([('Content-Type', 'text/plain')]),
+                          set(self._headers))
+
+    def test_forbidden(self):
+        self._req.cache_forever()  # cache headers should be discarded
+        message = 'Something not found'
+        self.assertEquals(message, self._req.forbidden(message))
+        self.assertEquals(HTTP_FORBIDDEN, self._status)
+        self.assertEquals(set([('Content-Type', 'text/plain')]),
+                          set(self._headers))
+
+    def test_respond_ok(self):
+        self._req.respond()
+        self.assertEquals([], self._headers)
+        self.assertEquals(HTTP_OK, self._status)
+
+    def test_respond(self):
+        self._req.nocache()
+        self._req.respond(status=402, content_type='some/type',
+                          headers=[('X-Foo', 'foo'), ('X-Bar', 'bar')])
+        self.assertEquals(set([
+          ('X-Foo', 'foo'),
+          ('X-Bar', 'bar'),
+          ('Content-Type', 'some/type'),
+          ('Expires', 'Fri, 01 Jan 1980 00:00:00 GMT'),
+          ('Pragma', 'no-cache'),
+          ('Cache-Control', 'no-cache, max-age=0, must-revalidate'),
+          ]), set(self._headers))
+        self.assertEquals(402, self._status)
+
+
+class HTTPGitApplicationTestCase(TestCase):
+
+    def setUp(self):
+        super(HTTPGitApplicationTestCase, self).setUp()
+        self._app = HTTPGitApplication('backend')
+
+    def test_call(self):
+        def test_handler(req, backend, mat):
+            # tests interface used by all handlers
+            self.assertEquals(environ, req.environ)
+            self.assertEquals('backend', backend)
+            self.assertEquals('/foo', mat.group(0))
+            return 'output'
+
+        self._app.services = {
+          ('GET', re.compile('/foo$')): test_handler,
+        }
+        environ = {
+          'PATH_INFO': '/foo',
+          'REQUEST_METHOD': 'GET',
+          }
+        self.assertEquals('output', self._app(environ, None))

=== added file 'dulwich/tests/utils.py'
--- dulwich/tests/utils.py	1970-01-01 00:00:00 +0000
+++ dulwich/tests/utils.py	2010-12-18 17:01:24 +0000
@@ -0,0 +1,149 @@
+# utils.py -- Test utilities for Dulwich.
+# Copyright (C) 2010 Google, Inc.
+#
+# 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.
+
+"""Utility functions common to Dulwich tests."""
+
+
+import datetime
+import os
+import shutil
+import tempfile
+import time
+import types
+
+from dulwich.objects import (
+    FixedSha,
+    Commit,
+    )
+from dulwich.repo import Repo
+from dulwich.tests import (
+    TestSkipped,
+    )
+
+
+def open_repo(name):
+    """Open a copy of a repo in a temporary directory.
+
+    Use this function for accessing repos in dulwich/tests/data/repos to avoid
+    accidentally or intentionally modifying those repos in place. Use
+    tear_down_repo to delete any temp files created.
+
+    :param name: The name of the repository, relative to
+        dulwich/tests/data/repos
+    :returns: An initialized Repo object that lives in a temporary directory.
+    """
+    temp_dir = tempfile.mkdtemp()
+    repo_dir = os.path.join(os.path.dirname(__file__), 'data', 'repos', name)
+    temp_repo_dir = os.path.join(temp_dir, name)
+    shutil.copytree(repo_dir, temp_repo_dir, symlinks=True)
+    return Repo(temp_repo_dir)
+
+
+def tear_down_repo(repo):
+    """Tear down a test repository."""
+    temp_dir = os.path.dirname(repo.path.rstrip(os.sep))
+    shutil.rmtree(temp_dir)
+
+
+def make_object(cls, **attrs):
+    """Make an object for testing and assign some members.
+
+    This method creates a new subclass to allow arbitrary attribute
+    reassignment, which is not otherwise possible with objects having __slots__.
+
+    :param attrs: dict of attributes to set on the new object.
+    :return: A newly initialized object of type cls.
+    """
+
+    class TestObject(cls):
+        """Class that inherits from the given class, but without __slots__.
+
+        Note that classes with __slots__ can't have arbitrary attributes monkey-
+        patched in, so this is a class that is exactly the same only with a
+        __dict__ instead of __slots__.
+        """
+        pass
+
+    obj = TestObject()
+    for name, value in attrs.iteritems():
+        if name == 'id':
+            # id property is read-only, so we overwrite sha instead.
+            sha = FixedSha(value)
+            obj.sha = lambda: sha
+        else:
+            setattr(obj, name, value)
+    return obj
+
+
+def make_commit(**attrs):
+    """Make a Commit object with a default set of members.
+
+    :param attrs: dict of attributes to overwrite from the default values.
+    :return: A newly initialized Commit object.
+    """
+    default_time = int(time.mktime(datetime.datetime(2010, 1, 1).timetuple()))
+    all_attrs = {'author': 'Test Author <test@xxxxxxxxxxxx>',
+                 'author_time': default_time,
+                 'author_timezone': 0,
+                 'committer': 'Test Committer <test@xxxxxxxxxxxx>',
+                 'commit_time': default_time,
+                 'commit_timezone': 0,
+                 'message': 'Test message.',
+                 'parents': [],
+                 'tree': '0' * 40}
+    all_attrs.update(attrs)
+    return make_object(Commit, **all_attrs)
+
+
+def functest_builder(method, func):
+    """Generate a test method that tests the given function."""
+
+    def do_test(self):
+        method(self, func)
+
+    return do_test
+
+
+def ext_functest_builder(method, func):
+    """Generate a test method that tests the given extension function.
+
+    This is intended to generate test methods that test both a pure-Python
+    version and an extension version using common test code. The extension test
+    will raise TestSkipped if the extension is not found.
+
+    Sample usage:
+
+    class MyTest(TestCase);
+        def _do_some_test(self, func_impl):
+            self.assertEqual('foo', func_impl())
+
+        test_foo = functest_builder(_do_some_test, foo_py)
+        test_foo_extension = ext_functest_builder(_do_some_test, _foo_c)
+
+    :param method: The method to run. It must must two parameters, self and the
+        function implementation to test.
+    :param func: The function implementation to pass to method.
+    """
+
+    def do_test(self):
+        if not isinstance(func, types.BuiltinFunctionType):
+            raise TestSkipped("%s extension not found", func.func_name)
+        method(self, func)
+
+    return do_test

=== added file 'dulwich/web.py'
--- dulwich/web.py	1970-01-01 00:00:00 +0000
+++ dulwich/web.py	2010-12-19 15:56:03 +0000
@@ -0,0 +1,415 @@
+# web.py -- WSGI smart-http server
+# Copyright (C) 2010 Google, Inc.
+#
+# 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
+# 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.
+
+"""HTTP server for dulwich that implements the git smart HTTP protocol."""
+
+from cStringIO import StringIO
+import os
+import re
+import sys
+import time
+
+try:
+    from urlparse import parse_qs
+except ImportError:
+    from dulwich._compat import parse_qs
+from dulwich import log_utils
+from dulwich.protocol import (
+    ReceivableProtocol,
+    )
+from dulwich.repo import (
+    Repo,
+    )
+from dulwich.server import (
+    DictBackend,
+    DEFAULT_HANDLERS,
+    )
+
+
+logger = log_utils.getLogger(__name__)
+
+
+# HTTP error strings
+HTTP_OK = '200 OK'
+HTTP_NOT_FOUND = '404 Not Found'
+HTTP_FORBIDDEN = '403 Forbidden'
+HTTP_ERROR = '500 Internal Server Error'
+
+
+def date_time_string(timestamp=None):
+    # From BaseHTTPRequestHandler.date_time_string in BaseHTTPServer.py in the
+    # Python 2.6.5 standard library, following modifications:
+    #  - Made a global rather than an instance method.
+    #  - weekdayname and monthname are renamed and locals rather than class
+    #    variables.
+    # Copyright (c) 2001-2010 Python Software Foundation; All Rights Reserved
+    weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+    months = [None,
+              'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+    if timestamp is None:
+        timestamp = time.time()
+    year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp)
+    return '%s, %02d %3s %4d %02d:%02d:%02d GMD' % (
+            weekdays[wd], day, months[month], year, hh, mm, ss)
+
+
+def url_prefix(mat):
+    """Extract the URL prefix from a regex match.
+
+    :param mat: A regex match object.
+    :returns: The URL prefix, defined as the text before the match in the
+        original string. Normalized to start with one leading slash and end with
+        zero.
+    """
+    return '/' + mat.string[:mat.start()].strip('/')
+
+
+def get_repo(backend, mat):
+    """Get a Repo instance for the given backend and URL regex match."""
+    return backend.open_repository(url_prefix(mat))
+
+
+def send_file(req, f, content_type):
+    """Send a file-like object to the request output.
+
+    :param req: The HTTPGitRequest object to send output to.
+    :param f: An open file-like object to send; will be closed.
+    :param content_type: The MIME type for the file.
+    :return: Iterator over the contents of the file, as chunks.
+    """
+    if f is None:
+        yield req.not_found('File not found')
+        return
+    try:
+        req.respond(HTTP_OK, content_type)
+        while True:
+            data = f.read(10240)
+            if not data:
+                break
+            yield data
+        f.close()
+    except IOError:
+        f.close()
+        yield req.error('Error reading file')
+    except:
+        f.close()
+        raise
+
+
+def _url_to_path(url):
+    return url.replace('/', os.path.sep)
+
+
+def get_text_file(req, backend, mat):
+    req.nocache()
+    path = _url_to_path(mat.group())
+    logger.info('Sending plain text file %s', path)
+    return send_file(req, get_repo(backend, mat).get_named_file(path),
+                     'text/plain')
+
+
+def get_loose_object(req, backend, mat):
+    sha = mat.group(1) + mat.group(2)
+    logger.info('Sending loose object %s', sha)
+    object_store = get_repo(backend, mat).object_store
+    if not object_store.contains_loose(sha):
+        yield req.not_found('Object not found')
+        return
+    try:
+        data = object_store[sha].as_legacy_object()
+    except IOError:
+        yield req.error('Error reading object')
+        return
+    req.cache_forever()
+    req.respond(HTTP_OK, 'application/x-git-loose-object')
+    yield data
+
+
+def get_pack_file(req, backend, mat):
+    req.cache_forever()
+    path = _url_to_path(mat.group())
+    logger.info('Sending pack file %s', path)
+    return send_file(req, get_repo(backend, mat).get_named_file(path),
+                     'application/x-git-packed-objects')
+
+
+def get_idx_file(req, backend, mat):
+    req.cache_forever()
+    path = _url_to_path(mat.group())
+    logger.info('Sending pack file %s', path)
+    return send_file(req, get_repo(backend, mat).get_named_file(path),
+                     'application/x-git-packed-objects-toc')
+
+
+def get_info_refs(req, backend, mat):
+    params = parse_qs(req.environ['QUERY_STRING'])
+    service = params.get('service', [None])[0]
+    if service and not req.dumb:
+        handler_cls = req.handlers.get(service, None)
+        if handler_cls is None:
+            yield req.forbidden('Unsupported service %s' % service)
+            return
+        req.nocache()
+        write = req.respond(HTTP_OK, 'application/x-%s-advertisement' % service)
+        proto = ReceivableProtocol(StringIO().read, write)
+        handler = handler_cls(backend, [url_prefix(mat)], proto,
+                              stateless_rpc=True, advertise_refs=True)
+        handler.proto.write_pkt_line('# service=%s\n' % service)
+        handler.proto.write_pkt_line(None)
+        handler.handle()
+    else:
+        # non-smart fallback
+        # TODO: select_getanyfile() (see http-backend.c)
+        req.nocache()
+        req.respond(HTTP_OK, 'text/plain')
+        logger.info('Emulating dumb info/refs')
+        repo = get_repo(backend, mat)
+        refs = repo.get_refs()
+        for name in sorted(refs.iterkeys()):
+            # get_refs() includes HEAD as a special case, but we don't want to
+            # advertise it
+            if name == 'HEAD':
+                continue
+            sha = refs[name]
+            o = repo[sha]
+            if not o:
+                continue
+            yield '%s\t%s\n' % (sha, name)
+            peeled_sha = repo.get_peeled(name)
+            if peeled_sha != sha:
+                yield '%s\t%s^{}\n' % (peeled_sha, name)
+
+
+def get_info_packs(req, backend, mat):
+    req.nocache()
+    req.respond(HTTP_OK, 'text/plain')
+    logger.info('Emulating dumb info/packs')
+    for pack in get_repo(backend, mat).object_store.packs:
+        yield 'P pack-%s.pack\n' % pack.name()
+
+
+class _LengthLimitedFile(object):
+    """Wrapper class to limit the length of reads from a file-like object.
+
+    This is used to ensure EOF is read from the wsgi.input object once
+    Content-Length bytes are read. This behavior is required by the WSGI spec
+    but not implemented in wsgiref as of 2.5.
+    """
+
+    def __init__(self, input, max_bytes):
+        self._input = input
+        self._bytes_avail = max_bytes
+
+    def read(self, size=-1):
+        if self._bytes_avail <= 0:
+            return ''
+        if size == -1 or size > self._bytes_avail:
+            size = self._bytes_avail
+        self._bytes_avail -= size
+        return self._input.read(size)
+
+    # TODO: support more methods as necessary
+
+
+def handle_service_request(req, backend, mat):
+    service = mat.group().lstrip('/')
+    logger.info('Handling service request for %s', service)
+    handler_cls = req.handlers.get(service, None)
+    if handler_cls is None:
+        yield req.forbidden('Unsupported service %s' % service)
+        return
+    req.nocache()
+    write = req.respond(HTTP_OK, 'application/x-%s-response' % service)
+
+    input = req.environ['wsgi.input']
+    # This is not necessary if this app is run from a conforming WSGI server.
+    # Unfortunately, there's no way to tell that at this point.
+    # TODO: git may used HTTP/1.1 chunked encoding instead of specifying
+    # content-length
+    content_length = req.environ.get('CONTENT_LENGTH', '')
+    if content_length:
+        input = _LengthLimitedFile(input, int(content_length))
+    proto = ReceivableProtocol(input.read, write)
+    handler = handler_cls(backend, [url_prefix(mat)], proto, stateless_rpc=True)
+    handler.handle()
+
+
+class HTTPGitRequest(object):
+    """Class encapsulating the state of a single git HTTP request.
+
+    :ivar environ: the WSGI environment for the request.
+    """
+
+    def __init__(self, environ, start_response, dumb=False, handlers=None):
+        self.environ = environ
+        self.dumb = dumb
+        self.handlers = handlers
+        self._start_response = start_response
+        self._cache_headers = []
+        self._headers = []
+
+    def add_header(self, name, value):
+        """Add a header to the response."""
+        self._headers.append((name, value))
+
+    def respond(self, status=HTTP_OK, content_type=None, headers=None):
+        """Begin a response with the given status and other headers."""
+        if headers:
+            self._headers.extend(headers)
+        if content_type:
+            self._headers.append(('Content-Type', content_type))
+        self._headers.extend(self._cache_headers)
+
+        return self._start_response(status, self._headers)
+
+    def not_found(self, message):
+        """Begin a HTTP 404 response and return the text of a message."""
+        self._cache_headers = []
+        logger.info('Not found: %s', message)
+        self.respond(HTTP_NOT_FOUND, 'text/plain')
+        return message
+
+    def forbidden(self, message):
+        """Begin a HTTP 403 response and return the text of a message."""
+        self._cache_headers = []
+        logger.info('Forbidden: %s', message)
+        self.respond(HTTP_FORBIDDEN, 'text/plain')
+        return message
+
+    def error(self, message):
+        """Begin a HTTP 500 response and return the text of a message."""
+        self._cache_headers = []
+        logger.error('Error: %s', message)
+        self.respond(HTTP_ERROR, 'text/plain')
+        return message
+
+    def nocache(self):
+        """Set the response to never be cached by the client."""
+        self._cache_headers = [
+          ('Expires', 'Fri, 01 Jan 1980 00:00:00 GMT'),
+          ('Pragma', 'no-cache'),
+          ('Cache-Control', 'no-cache, max-age=0, must-revalidate'),
+          ]
+
+    def cache_forever(self):
+        """Set the response to be cached forever by the client."""
+        now = time.time()
+        self._cache_headers = [
+          ('Date', date_time_string(now)),
+          ('Expires', date_time_string(now + 31536000)),
+          ('Cache-Control', 'public, max-age=31536000'),
+          ]
+
+
+class HTTPGitApplication(object):
+    """Class encapsulating the state of a git WSGI application.
+
+    :ivar backend: the Backend object backing this application
+    """
+
+    services = {
+      ('GET', re.compile('/HEAD$')): get_text_file,
+      ('GET', re.compile('/info/refs$')): get_info_refs,
+      ('GET', re.compile('/objects/info/alternates$')): get_text_file,
+      ('GET', re.compile('/objects/info/http-alternates$')): get_text_file,
+      ('GET', re.compile('/objects/info/packs$')): get_info_packs,
+      ('GET', re.compile('/objects/([0-9a-f]{2})/([0-9a-f]{38})$')): get_loose_object,
+      ('GET', re.compile('/objects/pack/pack-([0-9a-f]{40})\\.pack$')): get_pack_file,
+      ('GET', re.compile('/objects/pack/pack-([0-9a-f]{40})\\.idx$')): get_idx_file,
+
+      ('POST', re.compile('/git-upload-pack$')): handle_service_request,
+      ('POST', re.compile('/git-receive-pack$')): handle_service_request,
+    }
+
+    def __init__(self, backend, dumb=False, handlers=None):
+        self.backend = backend
+        self.dumb = dumb
+        self.handlers = dict(DEFAULT_HANDLERS)
+        if handlers is not None:
+            self.handlers.update(handlers)
+
+    def __call__(self, environ, start_response):
+        path = environ['PATH_INFO']
+        method = environ['REQUEST_METHOD']
+        req = HTTPGitRequest(environ, start_response, dumb=self.dumb,
+                             handlers=self.handlers)
+        # environ['QUERY_STRING'] has qs args
+        handler = None
+        for smethod, spath in self.services.iterkeys():
+            if smethod != method:
+                continue
+            mat = spath.search(path)
+            if mat:
+                handler = self.services[smethod, spath]
+                break
+        if handler is None:
+            return req.not_found('Sorry, that method is not supported')
+        return handler(req, self.backend, mat)
+
+
+# The reference server implementation is based on wsgiref, which is not
+# distributed with python 2.4. If wsgiref is not present, users will not be able
+# to use the HTTP server without a little extra work.
+try:
+    from wsgiref.simple_server import (
+        WSGIRequestHandler,
+        make_server,
+        )
+
+    class HTTPGitRequestHandler(WSGIRequestHandler):
+        """Handler that uses dulwich's logger for logging exceptions."""
+
+        def log_exception(self, exc_info):
+            logger.exception('Exception happened during processing of request',
+                             exc_info=exc_info)
+
+        def log_message(self, format, *args):
+            logger.info(format, *args)
+
+        def log_error(self, *args):
+            logger.error(*args)
+
+
+    def main(argv=sys.argv):
+        """Entry point for starting an HTTP git server."""
+        if len(argv) > 1:
+            gitdir = argv[1]
+        else:
+            gitdir = os.getcwd()
+
+        # TODO: allow serving on other addresses/ports via command-line flag
+        listen_addr=''
+        port = 8000
+
+        log_utils.default_logging_config()
+        backend = DictBackend({'/': Repo(gitdir)})
+        app = HTTPGitApplication(backend)
+        server = make_server(listen_addr, port, app,
+                             handler_class=HTTPGitRequestHandler)
+        logger.info('Listening for HTTP connections on %s:%d', listen_addr,
+                    port)
+        server.serve_forever()
+
+except ImportError:
+    # No wsgiref found; don't provide the reference functionality, but leave the
+    # rest of the WSGI-based implementation.
+    def main(argv=sys.argv):
+        """Stub entry point for failing to start a server without wsgiref."""
+        sys.stderr.write('Sorry, the wsgiref module is required for dul-web.\n')
+        sys.exit(1)

=== modified file 'setup.py'
--- setup.py	2009-10-25 18:57:52 +0000
+++ setup.py	2010-12-18 16:59:24 +0000
@@ -1,14 +1,14 @@
 #!/usr/bin/python
-# Setup file for bzr-git
-# Copyright (C) 2008-2009 Jelmer Vernooij <jelmer@xxxxxxxxx>
+# Setup file for dulwich
+# Copyright (C) 2008-2010 Jelmer Vernooij <jelmer@xxxxxxxxx>
 
 try:
-    from setuptools import setup
+    from setuptools import setup, Extension
 except ImportError:
-    from distutils.core import setup
-from distutils.extension import Extension
+    from distutils.core import setup, Extension
+from distutils.core import Distribution
 
-dulwich_version_string = '0.4.1'
+dulwich_version_string = '0.7.0'
 
 include_dirs = []
 # Windows MSVC support
@@ -17,6 +17,22 @@
     include_dirs.append('dulwich')
 
 
+class DulwichDistribution(Distribution):
+
+    def is_pure(self):
+        if self.pure:
+            return True
+
+    def has_ext_modules(self):
+        return not self.pure
+
+    global_options = Distribution.global_options + [
+        ('pure', None, 
+            "use pure (slower) Python code instead of C extensions")]
+
+    pure = False
+
+        
 setup(name='dulwich',
       description='Pure-Python Git Library',
       keywords='git',
@@ -32,11 +48,14 @@
       in one of the Monty Python sketches.
       """,
       packages=['dulwich', 'dulwich.tests'],
-      scripts=['bin/dulwich', 'bin/dul-daemon'],
-      ext_modules=[
+      scripts=['bin/dulwich', 'bin/dul-daemon', 'bin/dul-web'],
+      ext_modules = [
           Extension('dulwich._objects', ['dulwich/_objects.c'],
                     include_dirs=include_dirs),
           Extension('dulwich._pack', ['dulwich/_pack.c'],
-                    include_dirs=include_dirs),
+              include_dirs=include_dirs),
+          Extension('dulwich._diff_tree', ['dulwich/_diff_tree.c'],
+              include_dirs=include_dirs),
           ],
+      distclass=DulwichDistribution,
       )

# Begin bundle
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
ImJao+ud7t2e95/8j+l/N9v//eTyH87FHs0YXv/v7BDSC337FH/0Ojr8C/oyIB4QkAA6j4sTmWoP
J+TSP5wEp+cE4i8wAT6/sOztTwB7v+v9j4esRfwUzVVRTHbYOVI/g/0M/UGtlMP+1/6v7jZA2f1y
R/sp0/axPl/3welg/6nTknR/M/3OiKf+6hvgSYn9xpT/Wih/wP/D/2P32x+L/c/1/QIm353s/rbG
EbfvPyX5hB7x8skhhXtZjx/qyU6wpzEi/ySEU/LaT9rA3/20F0W/7C20h28ft+f9Pc8pD/MpP67/
APu9+aQ8kKM2K3Sfmng/2Bfyn51CcpRuegNh+jUrT9V+rMQIJRVLh6PSq+n9mrof3/9/+YP6j8Xn
6A/R1x/J6/W/0vzf/r6v+7/sf3v87/d/pz/k/0f6rx/y/H/J/Hzz+hz+1/Xfmf/p/z/df2v3X/R/
of+j9b//v4n9x+c/wf2f6n+j/vOf+T/vf1n6n/zfn/+v81/6/uP3//V+m/o/z/8af+5+J+6P9j7z
/J/Z//r+xkf9H7n/k5/Uy/Rfuv/Z+t/vPt/zf6j6P239Nf9P+L7Pw/8Sn5T7H0PqfkJ/o/3/2vzX
9RL+W+2/k/nvxafvP8//U/I/e/qP1X+X/r/z34n3n45vzP6X+n/Yf9v9tj95/K/f/q/2P/H+v/5f
36/8f/b8v6iH7j8l+J/3/3f9LD8sfW/9tv0n5I/I/6zH99/iMn+z/ffxf8H1/uf9b9P/q/zn+t9j
979j/6/lPR9T/a/en678b81/m/9nl+N/j/sP03/Z91+L5/zK/2nq/rPrfuE+h+z/tP8X+q/4f4X5
H/5/x/8Bn/xf8H/T9vr/bfY/2P6//W/l/9Kvwfr/k++/hfx/b+S/D/gfov7P9j/D/m/8f95+h/Uf
6/7L9b9bnX5r6/9r+c/O+D+N95++/if+v/y/7P6P9F+DX/L/t/t/ZD9t+i/T/bfyf13/g/0f5Gf1
x+0/WL/H/L/svuv5H7n9x/5v/d/Uf9P6z+R/l/03+F91/GPr/0Po/+Pz/P/2fR++/qfk+h+1/1Pw
v+D87/mfhf8H/T4/Uf5//7fnPyH9p/B+f/i/2/j/6/8X7v9R+e+3/ffkP4P9z+g+r6f+H6X9f6vy
391/hfnv0f/e/c/n/8j9h/S/3P+ff/D/4P8X8LfP538t7/5P/qx+v/yf4P6H+J/8/1aJ+k+X4fuf
+z9H+7/vfj/4/P91/V/w/5X6b9v//H/N+H+b9C+//L/n/2n9X/O/0P5n8T/X9P7v+B/NV/z/1B94
fxj/D/rv039wf3/3H83/t/+E/DQ/2/4X434Pzf+f8qfvf/5+x+u/p/3n69D+F/z/uD/zn73/5frP
QH74/a/5P/u/1zJj+//kfF+/r83/iY/u/9Ff+b9X/K9P/OH90UP/f/kT9P6P/f/2/vP9D/l9h+1/
3Py395+U/7P8z8b/K/e/nP/h+q/Ye//L/f/mv33/l/dfH/P/2Pr+1/ef9X6L0f2X/H/h/6f/N/zf
/P/i/Of23+V+Q/Xf1/8j4v4P/d/t/8L+H/u/8kP/j+kZ/4Xw/3vt/0/236//o/2P6T+w/6P+j8T/
X9/8v/Av/Z/5H+1/n/wP5b5v6r/f/Pf637r739Z+m/lf2X3f+d+4/dc/E/Rfr7/tf3f/f+2+H+W/
hf1n/T/gfkvuv5X9j+0KfoPvP9L939U/Y6/oG/rYf0//0/YfwfV/bfof66nf4X9Z+b/T/0v+t+Gc
/ov4v+p+h/8f9h/R/xf/J+T/sP5f/vf9v3f9E//+fjfpP3/9Z/+Po/43v/ff6Ev2n5f9z/C/G/M/
3v6H/8/td//b/e/9nX2fd/E7/+/5b+D/G/jf539j/H+t+3/PfxP339Inu/G/s9fqf9P+L/UftvZ/
6PyX5j+s/n/zP+N+W9v5/8b+j/Yff/8f6X86ntP/f+2fx+a/8nX/D/nfl//D+W3//X9R/z/7X51v
XH8P+93/F/0f9Xn+H+k/i/xfzx++P7D8D+n/y/63/xf+n/f+39X7n5P339z//5igrJMprMDC7LCC
pfnvwDI6vn///7////9////9Mgb/nyQvFAEvgAA7vuF8KAeADYXAD3dKAFULeZ17s7DgKKc5QVh7
HS9yC9ggpKmwYzNsqmUxRVQBbAAaLMaAAFB9ADSjRoABQUAAATgFAAAYAAAOgAA6ALmh58AAAAAA
AAXHHlMABtM2QwADTvQFSgFCgVFOAAANmwyjRl72e6AcDtOfXtRZ5DnbHudpyU0y3Mdacu7uHUbH
SnZO427us2DE1m121uy5dwa6tYTbvgAALB73cG5lAEJI1S7NFdtO3Vd26Ouh4AA3z2xQ9wcdzr6K
165aHTgu7ByoajILAFLW647AVLpm2iS7ANZsda67bqg6FaBbOtZxgUfAAAPb3jUKUq7uu7tFaNBR
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
FV5T39vHOZJbf826rT7FDG+DshCrkjjgjiAEDEjEcEAjEEQ6h7Ow9iGXna5J9hY/WL4b2GvsERsi
wXtwH49EGQeIF1XV76JSrq+wngYmbXcCL0eparOPwNnzNYvd0oy0mACzRMv99Je/Dp1vqOfZlOIX
4M6j66iD7f34yW0Z2Jji5L3kyH7AXVEU1qxxi+sPD3JMbpNslCABPauDs2j6j2qWXUysmLx421cu
vdxW2qpJAeTEDyOXv5oRiv7I7CmE7GKvibXYeay8lkI1eebCuU4ZvUTnQUrsnf9B+z5crB3P20MT
S4Yu58zO1Z9kEhSzniIRAW18zwLgQVEp4QkZCBPnfULbooUfrFBq2d30593o9433QgMX9oIbiG8t
bq7k6IXSAtPMeLzs405QYSSz0AzOpIzxTjXKXs+AbffTTjq4MtGgKf33RPdKo7XvKHfIETie0RuE
+MHL7bi+iF3wPPu2UjsLv2t4twqYeZTEaFCINapF1vxre9m94S5gUcBkeOyU+qs0TcnVuoIQWadA
G27q4+M0l269hQeqa19VEvt3xTCT22YA5Oqx1u7MkWvEk/qxEBOREH0AiJxIAhdlQB1t5NWDLls8
WaXJYcvjxHDxNYw6I9wS1XSHjuoYj4UbUA3jyWcAAGucw4/ws8gS3cU539GHZxRVy6RaGnJ8wBE1
tR6DmTEhTt5sYzbzLMVOX91exLf35ZLlV0CW0r7m1YOIIh0u2gQFbYIAgLEq3j3Xdlgxt858+3J4
Yl2KV3MeOYiIEBdMBOUAhNqy8tPoRkCAb79tSR4MTUknrOV6EwoT1rDdXKW6AARr6vPDZZfpOavn
Dlo7y0ouoAvfn0K8VN73w7GRBnpja6ld8Ja9TEvOo4Tqnc3XfEeDVib2XH68sPZMADrmf4dcqpAl
heunYmzdVtuFR9/Xfc46tcsfTFFt7uHTnV2WcFfjv+H9OHa+GePh2baW0toqrbZbS2y221VtttLb
bS2rbbbbbaUtKtq21bbLbbS2qstpUS22222lLSrbbbbbYtthVttttKW222y220patttpUG2220to
ttLaW2222220tq222rFLbbbbbVtqlW22llttLbbVLbbRbbbRS222W22y2222lttoVS2KpS0pbbS2
20tttLaLbVW2i20paKttLattlLVVbbbbbFtsLaUttpVtC222220tttVS2222ltlW2220Vbattttt
tttttttpWtttottUtoVbbbbZbVtqlLSlttW220pbbbbFttttsW2qW2220tttLbbbbbbbbS220tq2
1bbbbbLbbVttttqlLS2iltW2222rbbbbS221baW1bbbZbS2i20UUW2qW1VtttltK1W2ltVbbbbbb
baKpbbaW1bbbVLbbS2222rbVKjbbVttttttVbbFttttqlW0tttLbbbapVtttttttFtv1/Ln3w0ZW
xhhvXhqZNCJnloZJd++voOK61T+OsSYnzboLuC2RSZ7/P8fs6qvfLV6dznvUyaDGAys52dehTfsQ
/S2kKqkBBjSYgMQNIIQ7kLN3UvJgelNILDeUTPAYxq3nk5YEcTTryJE5xQKHEB+51MXzda+fq9Tv
dG2222lXYPq28vl5223Xs7XC+zqU0ny/IL/OxBsOfkXorxITdL5tYHjRrN9+l7DlMKwo18x0AON3
w8vBnfItHH5VIq4V6ejnqTkHVqN4S5ch/IQzluFlk3rw0o547j37njL7XrGcub2c/nTwGXpof/P8
2a07V99/W1fk143tIKOxqz4SQH7OcxJ2tOlbksRr2q+k7fem2sOsagohOXPRkBjACpPWO8M1ufOd
SvwVS+IkD/AQkBAGACIwABi2aVfWSwwndy+8ntT3ymzLw5oMt2zd9uKzVskQIqCbQATnvFYuCzw3
q3ciFeCrREVeWHTrqyr5se3re5XwVacd3G8RZJQTU2tAh8UBG0UBx7mWpAW/QQUMK0+8MF/PxmKW
e6x76IOXJvSnACCIAAwRN6gQtAAAUAERCFa/Y4bI4HoH9zNItuyJbtN3klp8OJ4sz2Fq80z5Dmvd
bu2iIgV0JACmuvrrmv1U5t2j05F0W5bfL/S7dXq7dXu3PrAKwUoIx3y5nL6gILEGEAEiSSMZJEgM
kEk8RCEgXvJ6e2OOtIBMgiEPZ2/ujoXob1XdKqJJ++K/Pqw6IHvdT+Don0qBQAF2afbg1N73q+Xr
s3lwb1FvFqnXc01d7MOdTWvgxXbuTPgo0X9SYucLAU0c49W29c1c9vTyuqur54drYIiv5w9iRvmy
YNduTNHdWpyCywDAlDpF8sUh0xoA74g1Tjkux5JGdf8y61R64TKSPWUE8NR7fdarw4x/e12Mo/ud
sn1XZY/cXay7UFXhl4YOHIgD2XjkUrNmLaLgnnn0+adsGrtY+MyP0crP/iaOiECctIqTLwSgUTCm
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
FFkBSCRILEEgjEQRRgKoDEBYRYMEZBGRAFiIiEVQFBVgyMFUYgiKRVWAxFEGLAYskGAoixERRVIg
xFRQERipIkUVBUIIhEFFRkWCJERYqKggisBYqgqIxgxisVEiKEEYIqrEYgiCLFjBZFFWMRBEYKIk
kYkRiiwRBBVUVUWIIowQWSRBUGJGKioKiMEjBQVWIIhBEMliMQEBISCQkFZCSJJJUQBZIKSIySSk
IDCoAKSIwiBEWQgoAiIQpIMICQIBJSBRJIMgkkEAZAYTvGKxQWKKsWACqqyKKqqqiwWKsVRRRViq
KLFVQWCiiqoqqKsUFFIosUUVYqxVVVirAFFEVVVFiixVVEWKqqoqxVVRVFAWKCkUVRRRRYKCqqiq
KqqqqKoqiiqqqqiiiiiiMWKqiqqrFFFFVVFWRRVVVFUBEVQVVUWEFBVWKjFVYqrBQiqoCirFVZFF
gLFiqoqiqCiiiwVVWKLFWKKosUVRVRFFUFVEVRVgKoqxRVFFFUVQVRYLFWKosVVVRRYoqqsFUVRV
FFVRRVFIsUWAoosUWEFVVUWRRFRYqqsFUVRVFRixYsVRRVFiqqqoLFWCiiqqqKqgoojFUVRVVVFV
VkBRZERFRRRVVRERFBVgoKSLBViqKoqrFFiiiiiqqgqqLFiigsVVFUFIsBVVRViiqqqLFFFVRRYq
rFFVVBRYoqgoioosVFYoqqqrFFFGwGqCihFGySBBJGAEJxkkO6ySccLAFhA6TAN6EJiEn9SBCT7I
QAkYAySEP+Ie2HCDO+wgVCSIMCJN7ISE/1z+zu2aI85iSYwvR+eEREHgRECAj07UrPdE61Y4f59/
OmJm6nsn59uuyNlLDw3ZP4nJ28Utb/i3+fetstBg08a/C6n/WLqrv94Dlot19mM+v9h8JYmmVdTu
RiKj/JMT7bf8s2AXP4PG3M/kWd0av5Knqqypav2exTved7ZoXOamXwuds+NCw/9RekoYdqEoFrV2
/9/q697u+pnreRTEbSbGV7/30ujgFEfG5mtERAEUEi0Lbi2zY3rzdGNq+7hssZ9N1GuTx2uaFDZ0
q8uOprH/daAEE6YvQjfFb/AeTsdbmyHt8gaIQHOM8Qeb1yQiE7/7Wl5DtBymMQ5jVEYjLP2PCVnV
tbgvi/r9mYV+PEMrpesYwr6DuqIoqMiKjLsl4uZ9jQLwJWK3sPRoJQHEx5Uom0rtJigdmKaXQdbj
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
H/5//i7kinChIbHsTrQ=

Follow ups