diff --git a/Bindings/Libgit2.hs b/Bindings/Libgit2.hs
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2.hs
@@ -0,0 +1,36 @@
+
+module Bindings.Libgit2 (
+    module Bindings.Libgit2.Refs,
+    module Bindings.Libgit2.Odb,
+    module Bindings.Libgit2.Types,
+    module Bindings.Libgit2.Index,
+    module Bindings.Libgit2.ThreadUtils,
+    module Bindings.Libgit2.Oid,
+    module Bindings.Libgit2.Tag,
+    module Bindings.Libgit2.Object,
+    module Bindings.Libgit2.Signature,
+    module Bindings.Libgit2.Blob,
+    module Bindings.Libgit2.OdbBackend,
+    module Bindings.Libgit2.Repository,
+    module Bindings.Libgit2.Common,
+    module Bindings.Libgit2.Commit,
+    module Bindings.Libgit2.Errors,
+    module Bindings.Libgit2.Tree,
+    module Bindings.Libgit2.Revwalk) where
+import Bindings.Libgit2.Refs
+import Bindings.Libgit2.Odb
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Index
+import Bindings.Libgit2.ThreadUtils
+import Bindings.Libgit2.Oid
+import Bindings.Libgit2.Tag
+import Bindings.Libgit2.Object
+import Bindings.Libgit2.Signature
+import Bindings.Libgit2.Blob
+import Bindings.Libgit2.OdbBackend
+import Bindings.Libgit2.Repository
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Commit
+import Bindings.Libgit2.Errors
+import Bindings.Libgit2.Tree
+import Bindings.Libgit2.Revwalk
diff --git a/Bindings/Libgit2/Blob.hsc b/Bindings/Libgit2/Blob.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Blob.hsc
@@ -0,0 +1,17 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Blob where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+import Bindings.Libgit2.Object
+#ccall git_blob_set_rawcontent_fromfile , Ptr <git_blob> -> CString -> IO (CInt)
+#ccall git_blob_set_rawcontent , Ptr <git_blob> -> Ptr Word8 -> CSize -> IO (CInt)
+#ccall git_blob_rawcontent , Ptr <git_blob> -> IO (Ptr Word8)
+#ccall git_blob_rawsize , Ptr <git_blob> -> IO (CInt)
+#ccall git_blob_writefile , Ptr <git_oid> -> Ptr <git_repository> -> CString -> IO (CInt)
+#cinline git_blob_lookup , Ptr (Ptr <git_blob>) -> Ptr <git_repository> -> Ptr <git_oid> -> IO (CInt)
+#cinline git_blob_new , Ptr (Ptr <git_blob>) -> Ptr <git_repository> -> IO (CInt)
diff --git a/Bindings/Libgit2/Blob.hsc.helper.c b/Bindings/Libgit2/Blob.hsc.helper.c
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Blob.hsc.helper.c
@@ -0,0 +1,6 @@
+
+#include <bindings.cmacros.h>
+#include <git2.h>
+
+BC_INLINE3(git_blob_lookup, git_blob **, git_repository *, const git_oid *,int)
+BC_INLINE2(git_blob_new, git_blob **, git_repository *,int)
diff --git a/Bindings/Libgit2/Commit.hsc b/Bindings/Libgit2/Commit.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Commit.hsc
@@ -0,0 +1,27 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Commit where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+import Bindings.Libgit2.Object
+#ccall git_commit_id , Ptr <git_commit> -> IO (Ptr <git_oid>)
+#ccall git_commit_message_short , Ptr <git_commit> -> IO (CString)
+#ccall git_commit_message , Ptr <git_commit> -> IO (CString)
+#ccall git_commit_time , Ptr <git_commit> -> IO (CTime)
+#ccall git_commit_time_offset , Ptr <git_commit> -> IO (CInt)
+#ccall git_commit_committer , Ptr <git_commit> -> IO (Ptr <git_signature>)
+#ccall git_commit_author , Ptr <git_commit> -> IO (Ptr <git_signature>)
+#ccall git_commit_tree , Ptr (Ptr <git_tree>) -> Ptr <git_commit> -> IO (CInt)
+#ccall git_commit_parentcount , Ptr <git_commit> -> IO (CUInt)
+#ccall git_commit_parent , Ptr (Ptr <git_commit>) -> Ptr <git_commit> -> CUInt -> IO (CInt)
+#ccall git_commit_add_parent , Ptr <git_commit> -> Ptr <git_commit> -> IO (CInt)
+#ccall git_commit_set_message , Ptr <git_commit> -> CString -> IO ()
+#ccall git_commit_set_committer , Ptr <git_commit> -> Ptr <git_signature> -> IO ()
+#ccall git_commit_set_author , Ptr <git_commit> -> Ptr <git_signature> -> IO ()
+#ccall git_commit_set_tree , Ptr <git_commit> -> Ptr <git_tree> -> IO (CInt)
+#cinline git_commit_lookup , Ptr (Ptr <git_commit>) -> Ptr <git_repository> -> Ptr <git_oid> -> IO (CInt)
+#cinline git_commit_new , Ptr (Ptr <git_commit>) -> Ptr <git_repository> -> IO (CInt)
diff --git a/Bindings/Libgit2/Commit.hsc.helper.c b/Bindings/Libgit2/Commit.hsc.helper.c
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Commit.hsc.helper.c
@@ -0,0 +1,6 @@
+
+#include <bindings.cmacros.h>
+#include <git2.h>
+
+BC_INLINE3(git_commit_lookup, git_commit **, git_repository *, const git_oid *,int)
+BC_INLINE2(git_commit_new, git_commit **, git_repository *,int)
diff --git a/Bindings/Libgit2/Common.hsc b/Bindings/Libgit2/Common.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Common.hsc
@@ -0,0 +1,39 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Common where
+#strict_import
+
+import Bindings.Libgit2.ThreadUtils
+#num    GIT_SUCCESS
+#num    GIT_ERROR
+#num    GIT_ENOTOID
+#num    GIT_ENOTFOUND
+#num    GIT_ENOMEM
+#num    GIT_EOSERR
+#num    GIT_EOBJTYPE
+#num    GIT_EOBJCORRUPTED
+#num    GIT_ENOTAREPO
+#num    GIT_EINVALIDTYPE
+#num    GIT_EMISSINGOBJDATA
+#num    GIT_EPACKCORRUPTED
+#num    GIT_EFLOCKFAIL
+#num    GIT_EZLIB
+#num    GIT_EBUSY
+#num    GIT_EBAREINDEX
+#num    GIT_EINVALIDREFNAME
+#num    GIT_EREFCORRUPTED
+#num    GIT_ETOONESTEDSYMREF
+#num    GIT_EPACKEDREFSCORRUPTED
+#num    GIT_EINVALIDPATH
+#num    GIT_EREVWALKOVER
+#num    GIT_EINVALIDREFSTATE
+{- typedef struct {
+	char **strings;
+	size_t count;
+} git_strarray; -}
+#starttype git_strarray
+#field    strings , Ptr CString
+#field    count , CSize
+#stoptype
+#ccall git_strarray_free , Ptr <git_strarray> -> IO ()
diff --git a/Bindings/Libgit2/Errors.hsc b/Bindings/Libgit2/Errors.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Errors.hsc
@@ -0,0 +1,8 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Errors where
+#strict_import
+
+
+#ccall git_strerror , CInt -> IO (CString)
diff --git a/Bindings/Libgit2/Index.hsc b/Bindings/Libgit2/Index.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Index.hsc
@@ -0,0 +1,67 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Index where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+#num    GIT_IDXENTRY_NAMEMASK
+#num    GIT_IDXENTRY_STAGEMASK
+#num    GIT_IDXENTRY_EXTENDED
+#num    GIT_IDXENTRY_VALID
+#num    GIT_IDXENTRY_STAGESHIFT
+{- typedef struct {
+	git_time_t seconds;
+	
+	unsigned int nanoseconds;
+} git_index_time; -}
+#starttype git_index_time
+#field    seconds , CTime
+#field    nanoseconds , CUInt
+#stoptype
+{- typedef struct git_index_entry {
+	git_index_time ctime;
+	git_index_time mtime;
+
+	unsigned int dev;
+	unsigned int ino;
+	unsigned int mode;
+	unsigned int uid;
+	unsigned int gid;
+	git_off_t file_size;
+
+	git_oid oid;
+
+	unsigned short flags;
+	unsigned short flags_extended;
+
+	char *path;
+} git_index_entry; -}
+#starttype git_index_entry
+#field    ctime , <git_index_time>
+#field    mtime , <git_index_time>
+#field    dev , CUInt
+#field    ino , CUInt
+#field    mode , CUInt
+#field    uid , CUInt
+#field    gid , CUInt
+#field    file_size , <git_off_t>
+#field    oid , <git_oid>
+#field    flags , CUShort
+#field    flags_extended , CUShort
+#field    path , CString
+#stoptype
+#ccall git_index_open_bare , Ptr (Ptr <git_index>) -> CString -> IO (CInt)
+#ccall git_index_open_inrepo , Ptr (Ptr <git_index>) -> Ptr <git_repository> -> IO (CInt)
+#ccall git_index_clear , Ptr <git_index> -> IO ()
+#ccall git_index_free , Ptr <git_index> -> IO ()
+#ccall git_index_read , Ptr <git_index> -> IO (CInt)
+#ccall git_index_write , Ptr <git_index> -> IO (CInt)
+#ccall git_index_find , Ptr <git_index> -> CString -> IO (CInt)
+#ccall git_index_add , Ptr <git_index> -> CString -> CInt -> IO (CInt)
+#ccall git_index_remove , Ptr <git_index> -> CInt -> IO (CInt)
+#ccall git_index_insert , Ptr <git_index> -> Ptr <git_index_entry> -> IO (CInt)
+#ccall git_index_get , Ptr <git_index> -> CInt -> IO (Ptr <git_index_entry>)
+#ccall git_index_entrycount , Ptr <git_index> -> IO (CUInt)
diff --git a/Bindings/Libgit2/Object.hsc b/Bindings/Libgit2/Object.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Object.hsc
@@ -0,0 +1,20 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Object where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+#ccall git_object_lookup , Ptr (Ptr <git_object>) -> Ptr <git_repository> -> Ptr <git_oid> -> <git_otype> -> IO (CInt)
+#ccall git_object_new , Ptr (Ptr <git_object>) -> Ptr <git_repository> -> <git_otype> -> IO (CInt)
+#ccall git_object_write , Ptr <git_object> -> IO (CInt)
+#ccall git_object_id , Ptr <git_object> -> IO (Ptr <git_oid>)
+#ccall git_object_type , Ptr <git_object> -> IO (<git_otype>)
+#ccall git_object_owner , Ptr <git_object> -> IO (Ptr <git_repository>)
+#ccall git_object_close , Ptr <git_object> -> IO ()
+#ccall git_object_type2string , <git_otype> -> IO (CString)
+#ccall git_object_string2type , CString -> IO (<git_otype>)
+#ccall git_object_typeisloose , <git_otype> -> IO (CInt)
+#ccall git_object__size , <git_otype> -> IO (CSize)
diff --git a/Bindings/Libgit2/Odb.hsc b/Bindings/Libgit2/Odb.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Odb.hsc
@@ -0,0 +1,30 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Odb where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+{- typedef struct {
+	void *data;          
+	size_t len;          
+	git_otype type;      
+} git_rawobj; -}
+#starttype git_rawobj
+#field    data , Ptr Word8
+#field    len , CSize
+#field    type , <git_otype>
+#stoptype
+#ccall git_odb_new , Ptr (Ptr <git_odb>) -> IO (CInt)
+#ccall git_odb_open , Ptr (Ptr <git_odb>) -> CString -> IO (CInt)
+#ccall git_odb_add_backend , Ptr <git_odb> -> Ptr <git_odb_backend> -> CInt -> IO (CInt)
+#ccall git_odb_add_alternate , Ptr <git_odb> -> Ptr <git_odb_backend> -> CInt -> IO (CInt)
+#ccall git_odb_close , Ptr <git_odb> -> IO ()
+#ccall git_odb_read , Ptr <git_rawobj> -> Ptr <git_odb> -> Ptr <git_oid> -> IO (CInt)
+#ccall git_odb_read_header , Ptr <git_rawobj> -> Ptr <git_odb> -> Ptr <git_oid> -> IO (CInt)
+#ccall git_odb_write , Ptr <git_oid> -> Ptr <git_odb> -> Ptr <git_rawobj> -> IO (CInt)
+#ccall git_odb_exists , Ptr <git_odb> -> Ptr <git_oid> -> IO (CInt)
+#ccall git_rawobj_hash , Ptr <git_oid> -> Ptr <git_rawobj> -> IO (CInt)
+#ccall git_rawobj_close , Ptr <git_rawobj> -> IO ()
diff --git a/Bindings/Libgit2/OdbBackend.hsc b/Bindings/Libgit2/OdbBackend.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/OdbBackend.hsc
@@ -0,0 +1,12 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.OdbBackend where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+import Bindings.Libgit2.Odb
+#ccall git_odb_backend_pack , Ptr (Ptr <git_odb_backend>) -> CString -> IO (CInt)
+#ccall git_odb_backend_loose , Ptr (Ptr <git_odb_backend>) -> CString -> IO (CInt)
diff --git a/Bindings/Libgit2/Oid.hsc b/Bindings/Libgit2/Oid.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Oid.hsc
@@ -0,0 +1,26 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Oid where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+#num    GIT_OID_RAWSZ
+#num    GIT_OID_HEXSZ
+#opaque_t git_oid_shorten
+{- typedef struct {
+	
+	unsigned char id[GIT_OID_RAWSZ];
+} git_oid; -}
+#starttype git_oid
+#array_field    id , Word8
+#stoptype
+#ccall git_oid_mkstr , Ptr <git_oid> -> CString -> IO (CInt)
+#ccall git_oid_mkraw , Ptr <git_oid> -> Ptr Word8 -> IO ()
+#ccall git_oid_fmt , CString -> Ptr <git_oid> -> IO ()
+#ccall git_oid_pathfmt , CString -> Ptr <git_oid> -> IO ()
+#ccall git_oid_allocfmt , Ptr <git_oid> -> IO (CString)
+#ccall git_oid_to_string , CString -> CSize -> Ptr <git_oid> -> IO (CString)
+#ccall git_oid_cpy , Ptr <git_oid> -> Ptr <git_oid> -> IO ()
+#ccall git_oid_cmp , Ptr <git_oid> -> Ptr <git_oid> -> IO (CInt)
diff --git a/Bindings/Libgit2/Refs.hsc b/Bindings/Libgit2/Refs.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Refs.hsc
@@ -0,0 +1,24 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Refs where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+#ccall git_reference_lookup , Ptr (Ptr <git_reference>) -> Ptr <git_repository> -> CString -> IO (CInt)
+#ccall git_reference_create_symbolic , Ptr (Ptr <git_reference>) -> Ptr <git_repository> -> CString -> CString -> IO (CInt)
+#ccall git_reference_create_oid , Ptr (Ptr <git_reference>) -> Ptr <git_repository> -> CString -> Ptr <git_oid> -> IO (CInt)
+#ccall git_reference_oid , Ptr <git_reference> -> IO (Ptr <git_oid>)
+#ccall git_reference_target , Ptr <git_reference> -> IO (CString)
+#ccall git_reference_type , Ptr <git_reference> -> IO (<git_rtype>)
+#ccall git_reference_name , Ptr <git_reference> -> IO (CString)
+#ccall git_reference_resolve , Ptr (Ptr <git_reference>) -> Ptr <git_reference> -> IO (CInt)
+#ccall git_reference_owner , Ptr <git_reference> -> IO (Ptr <git_repository>)
+#ccall git_reference_set_target , Ptr <git_reference> -> CString -> IO (CInt)
+#ccall git_reference_set_oid , Ptr <git_reference> -> Ptr <git_oid> -> IO (CInt)
+#ccall git_reference_rename , Ptr <git_reference> -> CString -> IO (CInt)
+#ccall git_reference_delete , Ptr <git_reference> -> IO (CInt)
+#ccall git_reference_packall , Ptr <git_repository> -> IO (CInt)
+#ccall git_reference_listall , Ptr <git_strarray> -> Ptr <git_repository> -> CUInt -> IO (CInt)
diff --git a/Bindings/Libgit2/Repository.hsc b/Bindings/Libgit2/Repository.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Repository.hsc
@@ -0,0 +1,17 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Repository where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+#ccall git_repository_open , Ptr (Ptr <git_repository>) -> CString -> IO (CInt)
+#ccall git_repository_open2 , Ptr (Ptr <git_repository>) -> CString -> CString -> CString -> CString -> IO (CInt)
+#ccall git_repository_open3 , Ptr (Ptr <git_repository>) -> CString -> Ptr <git_odb> -> CString -> CString -> IO (CInt)
+#ccall git_repository_database , Ptr <git_repository> -> IO (Ptr <git_odb>)
+#ccall git_repository_index , Ptr (Ptr <git_index>) -> Ptr <git_repository> -> IO (CInt)
+#ccall git_repository_free , Ptr <git_repository> -> IO ()
+#ccall git_repository_gc , Ptr <git_repository> -> IO (CInt)
+#ccall git_repository_init , Ptr (Ptr <git_repository>) -> CString -> CUInt -> IO (CInt)
diff --git a/Bindings/Libgit2/Revwalk.hsc b/Bindings/Libgit2/Revwalk.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Revwalk.hsc
@@ -0,0 +1,21 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Revwalk where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+#num    GIT_SORT_NONE
+#num    GIT_SORT_TOPOLOGICAL
+#num    GIT_SORT_TIME
+#num    GIT_SORT_REVERSE
+#ccall git_revwalk_new , Ptr (Ptr <git_revwalk>) -> Ptr <git_repository> -> IO (CInt)
+#ccall git_revwalk_reset , Ptr <git_revwalk> -> IO ()
+#ccall git_revwalk_push , Ptr <git_revwalk> -> Ptr <git_oid> -> IO (CInt)
+#ccall git_revwalk_hide , Ptr <git_revwalk> -> Ptr <git_oid> -> IO (CInt)
+#ccall git_revwalk_next , Ptr <git_oid> -> Ptr <git_revwalk> -> IO (CInt)
+#ccall git_revwalk_sorting , Ptr <git_revwalk> -> CUInt -> IO ()
+#ccall git_revwalk_free , Ptr <git_revwalk> -> IO ()
+#ccall git_revwalk_repository , Ptr <git_revwalk> -> IO (Ptr <git_repository>)
diff --git a/Bindings/Libgit2/Signature.hsc b/Bindings/Libgit2/Signature.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Signature.hsc
@@ -0,0 +1,11 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Signature where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+#ccall git_signature_new , CString -> CString -> CTime -> CInt -> IO (Ptr <git_signature>)
+#ccall git_signature_dup , Ptr <git_signature> -> IO (Ptr <git_signature>)
+#ccall git_signature_free , Ptr <git_signature> -> IO ()
diff --git a/Bindings/Libgit2/Tag.hsc b/Bindings/Libgit2/Tag.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Tag.hsc
@@ -0,0 +1,23 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Tag where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+import Bindings.Libgit2.Object
+#ccall git_tag_id , Ptr <git_tag> -> IO (Ptr <git_oid>)
+#ccall git_tag_target , Ptr (Ptr <git_object>) -> Ptr <git_tag> -> IO (CInt)
+#ccall git_tag_target_oid , Ptr <git_tag> -> IO (Ptr <git_oid>)
+#ccall git_tag_type , Ptr <git_tag> -> IO (<git_otype>)
+#ccall git_tag_name , Ptr <git_tag> -> IO (CString)
+#ccall git_tag_tagger , Ptr <git_tag> -> IO (Ptr <git_signature>)
+#ccall git_tag_message , Ptr <git_tag> -> IO (CString)
+#ccall git_tag_set_target , Ptr <git_tag> -> Ptr <git_object> -> IO (CInt)
+#ccall git_tag_set_name , Ptr <git_tag> -> CString -> IO ()
+#ccall git_tag_set_tagger , Ptr <git_tag> -> Ptr <git_signature> -> IO ()
+#ccall git_tag_set_message , Ptr <git_tag> -> CString -> IO ()
+#cinline git_tag_lookup , Ptr (Ptr <git_tag>) -> Ptr <git_repository> -> Ptr <git_oid> -> IO (CInt)
+#cinline git_tag_new , Ptr (Ptr <git_tag>) -> Ptr <git_repository> -> IO (CInt)
diff --git a/Bindings/Libgit2/Tag.hsc.helper.c b/Bindings/Libgit2/Tag.hsc.helper.c
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Tag.hsc.helper.c
@@ -0,0 +1,6 @@
+
+#include <bindings.cmacros.h>
+#include <git2.h>
+
+BC_INLINE3(git_tag_lookup, git_tag **, git_repository *, const git_oid *,int)
+BC_INLINE2(git_tag_new, git_tag **, git_repository *,int)
diff --git a/Bindings/Libgit2/ThreadUtils.hsc b/Bindings/Libgit2/ThreadUtils.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/ThreadUtils.hsc
@@ -0,0 +1,9 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.ThreadUtils where
+#strict_import
+
+
+#num    GIT_HAS_TLS
+#num    GIT_THREADS
diff --git a/Bindings/Libgit2/Tree.hsc b/Bindings/Libgit2/Tree.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Tree.hsc
@@ -0,0 +1,27 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Tree where
+#strict_import
+
+import Bindings.Libgit2.Common
+import Bindings.Libgit2.Types
+import Bindings.Libgit2.Oid
+import Bindings.Libgit2.Object
+#ccall git_tree_id , Ptr <git_tree> -> IO (Ptr <git_oid>)
+#ccall git_tree_entrycount , Ptr <git_tree> -> IO (CSize)
+#ccall git_tree_entry_byname , Ptr <git_tree> -> CString -> IO (Ptr <git_tree_entry>)
+#ccall git_tree_entry_byindex , Ptr <git_tree> -> CInt -> IO (Ptr <git_tree_entry>)
+#ccall git_tree_entry_attributes , Ptr <git_tree_entry> -> IO (CUInt)
+#ccall git_tree_entry_name , Ptr <git_tree_entry> -> IO (CString)
+#ccall git_tree_entry_id , Ptr <git_tree_entry> -> IO (Ptr <git_oid>)
+#ccall git_tree_entry_2object , Ptr (Ptr <git_object>) -> Ptr <git_tree_entry> -> IO (CInt)
+#ccall git_tree_add_entry , Ptr (Ptr <git_tree_entry>) -> Ptr <git_tree> -> Ptr <git_oid> -> CString -> CInt -> IO (CInt)
+#ccall git_tree_remove_entry_byindex , Ptr <git_tree> -> CInt -> IO (CInt)
+#ccall git_tree_remove_entry_byname , Ptr <git_tree> -> CString -> IO (CInt)
+#ccall git_tree_clear_entries , Ptr <git_tree> -> IO ()
+#ccall git_tree_entry_set_id , Ptr <git_tree_entry> -> Ptr <git_oid> -> IO ()
+#ccall git_tree_entry_set_name , Ptr <git_tree_entry> -> CString -> IO ()
+#ccall git_tree_entry_set_attributes , Ptr <git_tree_entry> -> CUInt -> IO (CInt)
+#cinline git_tree_lookup , Ptr (Ptr <git_tree>) -> Ptr <git_repository> -> Ptr <git_oid> -> IO (CInt)
+#cinline git_tree_new , Ptr (Ptr <git_tree>) -> Ptr <git_repository> -> IO (CInt)
diff --git a/Bindings/Libgit2/Tree.hsc.helper.c b/Bindings/Libgit2/Tree.hsc.helper.c
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Tree.hsc.helper.c
@@ -0,0 +1,6 @@
+
+#include <bindings.cmacros.h>
+#include <git2.h>
+
+BC_INLINE3(git_tree_lookup, git_tree **, git_repository *, const git_oid *,int)
+BC_INLINE2(git_tree_new, git_tree **, git_repository *,int)
diff --git a/Bindings/Libgit2/Types.hsc b/Bindings/Libgit2/Types.hsc
new file mode 100644
--- /dev/null
+++ b/Bindings/Libgit2/Types.hsc
@@ -0,0 +1,76 @@
+
+#include <bindings.dsl.h>
+#include <git2.h>
+module Bindings.Libgit2.Types where
+#strict_import
+
+
+#integral_t git_off_t
+{- typedef enum {
+	GIT_OBJ_ANY = -2,		/**< Object can be any of the following */
+	GIT_OBJ_BAD = -1,       /**< Object is invalid. */
+	GIT_OBJ__EXT1 = 0,      /**< Reserved for future use. */
+	GIT_OBJ_COMMIT = 1,     /**< A commit object. */
+	GIT_OBJ_TREE = 2,       /**< A tree (directory listing) object. */
+	GIT_OBJ_BLOB = 3,       /**< A file revision object. */
+	GIT_OBJ_TAG = 4,        /**< An annotated tag object. */
+	GIT_OBJ__EXT2 = 5,      /**< Reserved for future use. */
+	GIT_OBJ_OFS_DELTA = 6,  /**< A delta, base is given by an offset. */
+	GIT_OBJ_REF_DELTA = 7,  /**< A delta, base is given by object id. */
+} git_otype; -}
+#integral_t git_otype
+#num    GIT_OBJ_ANY
+#num    GIT_OBJ_BAD
+#num    GIT_OBJ__EXT1
+#num    GIT_OBJ_COMMIT
+#num    GIT_OBJ_TREE
+#num    GIT_OBJ_BLOB
+#num    GIT_OBJ_TAG
+#num    GIT_OBJ__EXT2
+#num    GIT_OBJ_OFS_DELTA
+#num    GIT_OBJ_REF_DELTA
+{- typedef enum {
+	GIT_REF_INVALID = 0, /** Invalid reference */
+	GIT_REF_OID = 1, /** A reference which points at an object id */
+	GIT_REF_SYMBOLIC = 2, /** A reference which points at another reference */
+	GIT_REF_PACKED = 4,
+	GIT_REF_HAS_PEEL = 8,
+	GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC|GIT_REF_PACKED,
+} git_rtype; -}
+#integral_t git_rtype
+#num    GIT_REF_INVALID
+#num    GIT_REF_OID
+#num    GIT_REF_SYMBOLIC
+#num    GIT_REF_PACKED
+#num    GIT_REF_HAS_PEEL
+#num    GIT_REF_LISTALL
+#opaque_t git_odb
+#opaque_t git_odb_backend
+#opaque_t git_repository
+#opaque_t git_object
+#opaque_t git_revwalk
+#opaque_t git_tag
+#opaque_t git_blob
+#opaque_t git_commit
+#opaque_t git_tree_entry
+#opaque_t git_tree
+#opaque_t git_index
+#opaque_t git_reference
+{- typedef struct git_time {
+	time_t time; 
+	int offset; 
+} git_time; -}
+#starttype git_time
+#field    time , CTime
+#field    offset , CInt
+#stoptype
+{- typedef struct git_signature {
+	char *name; 
+	char *email; 
+	git_time when; 
+} git_signature; -}
+#starttype git_signature
+#field    name , CString
+#field    email , CString
+#field    when , <git_time>
+#stoptype
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Sakari Jokinen, Jacob Stanley
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/hlibgit2.cabal b/hlibgit2.cabal
new file mode 100644
--- /dev/null
+++ b/hlibgit2.cabal
@@ -0,0 +1,179 @@
+
+Name:                hlibgit2
+Version:             0.1
+Synopsis:            Bindings to libgit2 v0.1.0-265-gb5c5f0f
+Description:         Generated bindings to libgit2.
+License-file:        LICENSE
+License:             MIT
+Author:              Sakari Jokinen, Jacob Stanley
+Maintainer:          sakariij@gmail.com
+Build-Type:          Simple
+Cabal-Version:       >=1.10
+Category:            FFI
+
+extra-source-files:
+  tests/Main.hs~
+  tests/Main.hs
+  tests/Main.o
+  tests/Main.hi
+  libgit2/include/git2.h
+  libgit2/include/git2/refs.h
+  libgit2/include/git2/odb.h
+  libgit2/include/git2/types.h
+  libgit2/include/git2/index.h
+  libgit2/include/git2/thread-utils.h
+  libgit2/include/git2/oid.h
+  libgit2/include/git2/tag.h
+  libgit2/include/git2/zlib.h
+  libgit2/include/git2/object.h
+  libgit2/include/git2/signature.h
+  libgit2/include/git2/blob.h
+  libgit2/include/git2/odb_backend.h
+  libgit2/include/git2/repository.h
+  libgit2/include/git2/common.h
+  libgit2/include/git2/commit.h
+  libgit2/include/git2/errors.h
+  libgit2/include/git2/tree.h
+  libgit2/include/git2/revwalk.h
+  libgit2/src/cc-compat.h
+  libgit2/src/refs.h
+  libgit2/src/odb.h
+  libgit2/src/delta-apply.h
+  libgit2/src/index.h
+  libgit2/src/thread-utils.h
+  libgit2/src/vector.h
+  libgit2/src/tag.h
+  libgit2/src/dir.h
+  libgit2/src/map.h
+  libgit2/src/signature.h
+  libgit2/src/blob.h
+  libgit2/src/hash.h
+  libgit2/src/fileops.h
+  libgit2/src/repository.h
+  libgit2/src/hashtable.h
+  libgit2/src/common.h
+  libgit2/src/util.h
+  libgit2/src/bswap.h
+  libgit2/src/t03-data.h
+  libgit2/src/filebuf.h
+  libgit2/src/mingw-compat.h
+  libgit2/src/commit.h
+  libgit2/src/pqueue.h
+  libgit2/src/msvc-compat.h
+  libgit2/src/tree.h
+  libgit2/src/block-sha1/sha1.h
+  libgit2/deps/zlib/inffixed.h
+  libgit2/deps/zlib/zconf.h
+  libgit2/deps/zlib/inflate.h
+  libgit2/deps/zlib/inftrees.h
+  libgit2/deps/zlib/zlib.h
+  libgit2/deps/zlib/trees.h
+  libgit2/deps/zlib/zutil.h
+  libgit2/deps/zlib/inffast.h
+  libgit2/deps/zlib/deflate.h
+  libgit2/src/win32/pthread.h
+
+Source-repository head
+  type: git
+  location: git://github.com/sakari/hlibgit2.git
+
+Source-repository this
+  type: git
+  location: git://github.com/sakari/hlibgit2.git
+  tag: hlibgit2-0.1
+
+test-suite smoke
+  default-language: Haskell98
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  hs-source-dirs: tests
+  build-depends:
+    base >=3,
+    hlibgit2,
+    process
+
+library
+  default-language: Haskell98
+  default-extensions:
+    ForeignFunctionInterface
+  build-depends:
+    base >= 3 && < 5,
+    bindings-DSL >= 1.0.9 && < 1.1
+  exposed-modules:
+    Bindings.Libgit2
+    Bindings.Libgit2.Refs
+    Bindings.Libgit2.Odb
+    Bindings.Libgit2.Types
+    Bindings.Libgit2.Index
+    Bindings.Libgit2.ThreadUtils
+    Bindings.Libgit2.Oid
+    Bindings.Libgit2.Tag
+    Bindings.Libgit2.Object
+    Bindings.Libgit2.Signature
+    Bindings.Libgit2.Blob
+    Bindings.Libgit2.OdbBackend
+    Bindings.Libgit2.Repository
+    Bindings.Libgit2.Common
+    Bindings.Libgit2.Commit
+    Bindings.Libgit2.Errors
+    Bindings.Libgit2.Tree
+    Bindings.Libgit2.Revwalk
+  c-sources:
+    Bindings/Libgit2/Tag.hsc.helper.c
+    Bindings/Libgit2/Blob.hsc.helper.c
+    Bindings/Libgit2/Commit.hsc.helper.c
+    Bindings/Libgit2/Tree.hsc.helper.c
+
+  include-dirs:
+    libgit2/include
+    libgit2/src
+    libgit2/src/block-sha1
+    libgit2/deps/zlib
+  c-sources:
+    libgit2/src/hash.c
+    libgit2/src/index.c
+    libgit2/src/pqueue.c
+    libgit2/src/filebuf.c
+    libgit2/src/hashtable.c
+    libgit2/src/util.c
+    libgit2/src/errors.c
+    libgit2/src/odb.c
+    libgit2/src/delta-apply.c
+    libgit2/src/odb_loose.c
+    libgit2/src/tree.c
+    libgit2/src/thread-utils.c
+    libgit2/src/revwalk.c
+    libgit2/src/oid.c
+    libgit2/src/odb_pack.c
+    libgit2/src/tag.c
+    libgit2/src/signature.c
+    libgit2/src/vector.c
+    libgit2/src/blob.c
+    libgit2/src/refs.c
+    libgit2/src/repository.c
+    libgit2/src/fileops.c
+    libgit2/src/object.c
+    libgit2/src/commit.c
+    libgit2/src/block-sha1/sha1.c
+    libgit2/deps/zlib/trees.c
+    libgit2/deps/zlib/zutil.c
+    libgit2/deps/zlib/inffast.c
+    libgit2/deps/zlib/adler32.c
+    libgit2/deps/zlib/deflate.c
+    libgit2/deps/zlib/inflate.c
+    libgit2/deps/zlib/inftrees.c
+
+  if os(windows)
+    cc-options: -DGIT_WIN32 -DNO_VIZ
+    include-dirs:
+      libgit2/src/win32
+    c-sources:
+      libgit2/src/win32/pthread.c
+      libgit2/src/win32/dir.c
+      libgit2/src/win32/fileops.c
+      libgit2/src/win32/map.c
+  else
+    include-dirs:
+      libgit2/src/unix
+    c-sources:
+      libgit2/src/unix/map.c
diff --git a/libgit2/deps/zlib/adler32.c b/libgit2/deps/zlib/adler32.c
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/adler32.c
@@ -0,0 +1,169 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2007 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#define local static
+
+local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
+
+#define BASE 65521UL    /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+#  define MOD(a) \
+    do { \
+        if (a >= (BASE << 16)) a -= (BASE << 16); \
+        if (a >= (BASE << 15)) a -= (BASE << 15); \
+        if (a >= (BASE << 14)) a -= (BASE << 14); \
+        if (a >= (BASE << 13)) a -= (BASE << 13); \
+        if (a >= (BASE << 12)) a -= (BASE << 12); \
+        if (a >= (BASE << 11)) a -= (BASE << 11); \
+        if (a >= (BASE << 10)) a -= (BASE << 10); \
+        if (a >= (BASE << 9)) a -= (BASE << 9); \
+        if (a >= (BASE << 8)) a -= (BASE << 8); \
+        if (a >= (BASE << 7)) a -= (BASE << 7); \
+        if (a >= (BASE << 6)) a -= (BASE << 6); \
+        if (a >= (BASE << 5)) a -= (BASE << 5); \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#  define MOD4(a) \
+    do { \
+        if (a >= (BASE << 4)) a -= (BASE << 4); \
+        if (a >= (BASE << 3)) a -= (BASE << 3); \
+        if (a >= (BASE << 2)) a -= (BASE << 2); \
+        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        if (a >= BASE) a -= BASE; \
+    } while (0)
+#else
+#  define MOD(a) a %= BASE
+#  define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long sum2;
+    unsigned n;
+
+    /* split Adler-32 into component sums */
+    sum2 = (adler >> 16) & 0xffff;
+    adler &= 0xffff;
+
+    /* in case user likes doing a byte at a time, keep it fast */
+    if (len == 1) {
+        adler += buf[0];
+        if (adler >= BASE)
+            adler -= BASE;
+        sum2 += adler;
+        if (sum2 >= BASE)
+            sum2 -= BASE;
+        return adler | (sum2 << 16);
+    }
+
+    /* initial Adler-32 value (deferred check for len == 1 speed) */
+    if (buf == Z_NULL)
+        return 1L;
+
+    /* in case short lengths are provided, keep it somewhat fast */
+    if (len < 16) {
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        if (adler >= BASE)
+            adler -= BASE;
+        MOD4(sum2);             /* only added so many BASE's */
+        return adler | (sum2 << 16);
+    }
+
+    /* do length NMAX blocks -- requires just one modulo operation */
+    while (len >= NMAX) {
+        len -= NMAX;
+        n = NMAX / 16;          /* NMAX is divisible by 16 */
+        do {
+            DO16(buf);          /* 16 sums unrolled */
+            buf += 16;
+        } while (--n);
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* do remaining bytes (less than NMAX, still just one modulo) */
+    if (len) {                  /* avoid modulos if none remaining */
+        while (len >= 16) {
+            len -= 16;
+            DO16(buf);
+            buf += 16;
+        }
+        while (len--) {
+            adler += *buf++;
+            sum2 += adler;
+        }
+        MOD(adler);
+        MOD(sum2);
+    }
+
+    /* return recombined sums */
+    return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off64_t len2;
+{
+    unsigned long sum1;
+    unsigned long sum2;
+    unsigned rem;
+
+    /* the derivation of this formula is left as an exercise for the reader */
+    rem = (unsigned)(len2 % BASE);
+    sum1 = adler1 & 0xffff;
+    sum2 = rem * sum1;
+    MOD(sum2);
+    sum1 += (adler2 & 0xffff) + BASE - 1;
+    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum1 >= BASE) sum1 -= BASE;
+    if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
+    if (sum2 >= BASE) sum2 -= BASE;
+    return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
+    uLong adler1;
+    uLong adler2;
+    z_off64_t len2;
+{
+    return adler32_combine_(adler1, adler2, len2);
+}
diff --git a/libgit2/deps/zlib/deflate.c b/libgit2/deps/zlib/deflate.c
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/deflate.c
@@ -0,0 +1,1834 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process depends on being able to identify portions
+ *      of the input text which are identical to earlier input (within a
+ *      sliding window trailing behind the input currently being processed).
+ *
+ *      The most straightforward technique turns out to be the fastest for
+ *      most input files: try all possible matches and select the longest.
+ *      The key feature of this algorithm is that insertions into the string
+ *      dictionary are very simple and thus fast, and deletions are avoided
+ *      completely. Insertions are performed at each input character, whereas
+ *      string matches are performed only when the previous match ends. So it
+ *      is preferable to spend more time in matches to allow very fast string
+ *      insertions and avoid deletions. The matching algorithm for small
+ *      strings is inspired from that of Rabin & Karp. A brute force approach
+ *      is used to find longer strings when a small match has been found.
+ *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ *      (by Leonid Broukhis).
+ *         A previous version of this file used a more sophisticated algorithm
+ *      (by Fiala and Greene) which is guaranteed to run in linear amortized
+ *      time, but has a larger average cost, uses more memory and is patented.
+ *      However the F&G algorithm may be faster for some highly redundant
+ *      files if the parameter max_chain_length (described below) is too large.
+ *
+ *  ACKNOWLEDGEMENTS
+ *
+ *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ *      I found it in 'freeze' written by Leonid Broukhis.
+ *      Thanks to many people for bug reports and testing.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ *      Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ *      A description of the Rabin and Karp algorithm is given in the book
+ *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ *      Fiala,E.R., and Greene,D.H.
+ *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+   " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ *  Function prototypes.
+ */
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window    OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast   OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow   OF((deflate_state *s, int flush));
+#endif
+local block_state deflate_rle    OF((deflate_state *s, int flush));
+local block_state deflate_huff   OF((deflate_state *s, int flush));
+local void lm_init        OF((deflate_state *s));
+local void putShortMSB    OF((deflate_state *s, uInt b));
+local void flush_pending  OF((z_streamp strm));
+local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifdef ASMV
+      void match_init OF((void)); /* asm code initialization */
+      uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match  OF((deflate_state *s, IPos cur_match));
+#endif
+
+#ifdef DEBUG
+local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                            int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+#  define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+   ush good_length; /* reduce lazy search above this match length */
+   ush max_lazy;    /* do not perform lazy search above this match length */
+   ush nice_length; /* quit search above this match length */
+   ush max_chain;
+   compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/*      good lazy nice chain */
+/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */
+/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4,    5, 16,    8, deflate_fast},
+/* 3 */ {4,    6, 32,   32, deflate_fast},
+
+/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */
+/* 5 */ {8,   16, 32,   32, deflate_slow},
+/* 6 */ {8,   16, 128, 128, deflate_slow},
+/* 7 */ {8,   32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
+ *    input characters, so that a running hash key can be computed from the
+ *    previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN  assertion: all calls to to INSERT_STRING are made with consecutive
+ *    input characters and the first MIN_MATCH bytes of str are valid
+ *    (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+    s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+    s->head[s->hash_size-1] = NIL; \
+    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+    z_streamp strm;
+    int level;
+    const char *version;
+    int stream_size;
+{
+    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+                         Z_DEFAULT_STRATEGY, version, stream_size);
+    /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+                  version, stream_size)
+    z_streamp strm;
+    int  level;
+    int  method;
+    int  windowBits;
+    int  memLevel;
+    int  strategy;
+    const char *version;
+    int stream_size;
+{
+    deflate_state *s;
+    int wrap = 1;
+    static const char my_version[] = ZLIB_VERSION;
+
+    ushf *overlay;
+    /* We overlay pending_buf and d_buf+l_buf. This works since the average
+     * output size for (length,distance) codes is <= 24 bits.
+     */
+
+    if (version == Z_NULL || version[0] != my_version[0] ||
+        stream_size != sizeof(z_stream)) {
+        return Z_VERSION_ERROR;
+    }
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+    strm->msg = Z_NULL;
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+    if (windowBits < 0) { /* suppress zlib wrapper */
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+#ifdef GZIP
+    else if (windowBits > 15) {
+        wrap = 2;       /* write gzip wrapper instead */
+        windowBits -= 16;
+    }
+#endif
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+        strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
+    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    if (s == Z_NULL) return Z_MEM_ERROR;
+    strm->state = (struct internal_state FAR *)s;
+    s->strm = strm;
+
+    s->wrap = wrap;
+    s->gzhead = Z_NULL;
+    s->w_bits = windowBits;
+    s->w_size = 1 << s->w_bits;
+    s->w_mask = s->w_size - 1;
+
+    s->hash_bits = memLevel + 7;
+    s->hash_size = 1 << s->hash_bits;
+    s->hash_mask = s->hash_size - 1;
+    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+    s->high_water = 0;      /* nothing written to s->window yet */
+
+    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+    s->pending_buf = (uchf *) overlay;
+    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+        s->pending_buf == Z_NULL) {
+        s->status = FINISH_STATE;
+        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        deflateEnd (strm);
+        return Z_MEM_ERROR;
+    }
+    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+    s->level = level;
+    s->strategy = strategy;
+    s->method = (Byte)method;
+
+    return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt  dictLength;
+{
+    deflate_state *s;
+    uInt length = dictLength;
+    uInt n;
+    IPos hash_head = 0;
+
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+        strm->state->wrap == 2 ||
+        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+        return Z_STREAM_ERROR;
+
+    s = strm->state;
+    if (s->wrap)
+        strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+    if (length < MIN_MATCH) return Z_OK;
+    if (length > s->w_size) {
+        length = s->w_size;
+        dictionary += dictLength - length; /* use the tail of the dictionary */
+    }
+    zmemcpy(s->window, dictionary, length);
+    s->strstart = length;
+    s->block_start = (long)length;
+
+    /* Insert all strings in the hash table (except for the last two bytes).
+     * s->lookahead stays null, so s->ins_h will be recomputed at the next
+     * call of fill_window.
+     */
+    s->ins_h = s->window[0];
+    UPDATE_HASH(s, s->ins_h, s->window[1]);
+    for (n = 0; n <= length - MIN_MATCH; n++) {
+        INSERT_STRING(s, n, hash_head);
+    }
+    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+        return Z_STREAM_ERROR;
+    }
+
+    strm->total_in = strm->total_out = 0;
+    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+    strm->data_type = Z_UNKNOWN;
+
+    s = (deflate_state *)strm->state;
+    s->pending = 0;
+    s->pending_out = s->pending_buf;
+
+    if (s->wrap < 0) {
+        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+    }
+    s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+    strm->adler =
+#ifdef GZIP
+        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+        adler32(0L, Z_NULL, 0);
+    s->last_flush = Z_NO_FLUSH;
+
+    _tr_init(s);
+    lm_init(s);
+
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+    z_streamp strm;
+    gz_headerp head;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+    strm->state->gzhead = head;
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+    z_streamp strm;
+    int bits;
+    int value;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    strm->state->bi_valid = bits;
+    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+    return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+    z_streamp strm;
+    int level;
+    int strategy;
+{
+    deflate_state *s;
+    compress_func func;
+    int err = Z_OK;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+
+#ifdef FASTEST
+    if (level != 0) level = 1;
+#else
+    if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+        return Z_STREAM_ERROR;
+    }
+    func = configuration_table[s->level].func;
+
+    if ((strategy != s->strategy || func != configuration_table[level].func) &&
+        strm->total_in != 0) {
+        /* Flush the last buffer: */
+        err = deflate(strm, Z_BLOCK);
+    }
+    if (s->level != level) {
+        s->level = level;
+        s->max_lazy_match   = configuration_table[level].max_lazy;
+        s->good_match       = configuration_table[level].good_length;
+        s->nice_match       = configuration_table[level].nice_length;
+        s->max_chain_length = configuration_table[level].max_chain;
+    }
+    s->strategy = strategy;
+    return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+    z_streamp strm;
+    int good_length;
+    int max_lazy;
+    int nice_length;
+    int max_chain;
+{
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    s = strm->state;
+    s->good_match = good_length;
+    s->max_lazy_match = max_lazy;
+    s->nice_match = nice_length;
+    s->max_chain_length = max_chain;
+    return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well.  The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds for
+ * every combination of windowBits and memLevel.  But even the conservative
+ * upper bound of about 14% expansion does not seem onerous for output buffer
+ * allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+    z_streamp strm;
+    uLong sourceLen;
+{
+    deflate_state *s;
+    uLong complen, wraplen;
+    Bytef *str;
+
+    /* conservative upper bound for compressed data */
+    complen = sourceLen +
+              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
+
+    /* if can't get parameters, return conservative bound plus zlib wrapper */
+    if (strm == Z_NULL || strm->state == Z_NULL)
+        return complen + 6;
+
+    /* compute wrapper length */
+    s = strm->state;
+    switch (s->wrap) {
+    case 0:                                 /* raw deflate */
+        wraplen = 0;
+        break;
+    case 1:                                 /* zlib wrapper */
+        wraplen = 6 + (s->strstart ? 4 : 0);
+        break;
+    case 2:                                 /* gzip wrapper */
+        wraplen = 18;
+        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */
+            if (s->gzhead->extra != Z_NULL)
+                wraplen += 2 + s->gzhead->extra_len;
+            str = s->gzhead->name;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            str = s->gzhead->comment;
+            if (str != Z_NULL)
+                do {
+                    wraplen++;
+                } while (*str++);
+            if (s->gzhead->hcrc)
+                wraplen += 2;
+        }
+        break;
+    default:                                /* for compiler happiness */
+        wraplen = 6;
+    }
+
+    /* if not default parameters, return conservative bound */
+    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+        return complen + wraplen;
+
+    /* default settings: return tight bound for that case */
+    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+           (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+    deflate_state *s;
+    uInt b;
+{
+    put_byte(s, (Byte)(b >> 8));
+    put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+    z_streamp strm;
+{
+    unsigned len = strm->state->pending;
+
+    if (len > strm->avail_out) len = strm->avail_out;
+    if (len == 0) return;
+
+    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    strm->next_out  += len;
+    strm->state->pending_out  += len;
+    strm->total_out += len;
+    strm->avail_out  -= len;
+    strm->state->pending -= len;
+    if (strm->state->pending == 0) {
+        strm->state->pending_out = strm->state->pending_buf;
+    }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    int old_flush; /* value of flush param for previous deflate call */
+    deflate_state *s;
+
+    if (strm == Z_NULL || strm->state == Z_NULL ||
+        flush > Z_BLOCK || flush < 0) {
+        return Z_STREAM_ERROR;
+    }
+    s = strm->state;
+
+    if (strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+        (s->status == FINISH_STATE && flush != Z_FINISH)) {
+        ERR_RETURN(strm, Z_STREAM_ERROR);
+    }
+    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+    s->strm = strm; /* just in case */
+    old_flush = s->last_flush;
+    s->last_flush = flush;
+
+    /* Write the header */
+    if (s->status == INIT_STATE) {
+#ifdef GZIP
+        if (s->wrap == 2) {
+            strm->adler = crc32(0L, Z_NULL, 0);
+            put_byte(s, 31);
+            put_byte(s, 139);
+            put_byte(s, 8);
+            if (s->gzhead == Z_NULL) {
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, 0);
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, OS_CODE);
+                s->status = BUSY_STATE;
+            }
+            else {
+                put_byte(s, (s->gzhead->text ? 1 : 0) +
+                            (s->gzhead->hcrc ? 2 : 0) +
+                            (s->gzhead->extra == Z_NULL ? 0 : 4) +
+                            (s->gzhead->name == Z_NULL ? 0 : 8) +
+                            (s->gzhead->comment == Z_NULL ? 0 : 16)
+                        );
+                put_byte(s, (Byte)(s->gzhead->time & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+                put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+                put_byte(s, s->level == 9 ? 2 :
+                            (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+                             4 : 0));
+                put_byte(s, s->gzhead->os & 0xff);
+                if (s->gzhead->extra != Z_NULL) {
+                    put_byte(s, s->gzhead->extra_len & 0xff);
+                    put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+                }
+                if (s->gzhead->hcrc)
+                    strm->adler = crc32(strm->adler, s->pending_buf,
+                                        s->pending);
+                s->gzindex = 0;
+                s->status = EXTRA_STATE;
+            }
+        }
+        else
+#endif
+        {
+            uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+            uInt level_flags;
+
+            if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+                level_flags = 0;
+            else if (s->level < 6)
+                level_flags = 1;
+            else if (s->level == 6)
+                level_flags = 2;
+            else
+                level_flags = 3;
+            header |= (level_flags << 6);
+            if (s->strstart != 0) header |= PRESET_DICT;
+            header += 31 - (header % 31);
+
+            s->status = BUSY_STATE;
+            putShortMSB(s, header);
+
+            /* Save the adler32 of the preset dictionary: */
+            if (s->strstart != 0) {
+                putShortMSB(s, (uInt)(strm->adler >> 16));
+                putShortMSB(s, (uInt)(strm->adler & 0xffff));
+            }
+            strm->adler = adler32(0L, Z_NULL, 0);
+        }
+    }
+#ifdef GZIP
+    if (s->status == EXTRA_STATE) {
+        if (s->gzhead->extra != Z_NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+
+            while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size)
+                        break;
+                }
+                put_byte(s, s->gzhead->extra[s->gzindex]);
+                s->gzindex++;
+            }
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (s->gzindex == s->gzhead->extra_len) {
+                s->gzindex = 0;
+                s->status = NAME_STATE;
+            }
+        }
+        else
+            s->status = NAME_STATE;
+    }
+    if (s->status == NAME_STATE) {
+        if (s->gzhead->name != Z_NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->name[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0) {
+                s->gzindex = 0;
+                s->status = COMMENT_STATE;
+            }
+        }
+        else
+            s->status = COMMENT_STATE;
+    }
+    if (s->status == COMMENT_STATE) {
+        if (s->gzhead->comment != Z_NULL) {
+            uInt beg = s->pending;  /* start of bytes to update crc */
+            int val;
+
+            do {
+                if (s->pending == s->pending_buf_size) {
+                    if (s->gzhead->hcrc && s->pending > beg)
+                        strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                            s->pending - beg);
+                    flush_pending(strm);
+                    beg = s->pending;
+                    if (s->pending == s->pending_buf_size) {
+                        val = 1;
+                        break;
+                    }
+                }
+                val = s->gzhead->comment[s->gzindex++];
+                put_byte(s, val);
+            } while (val != 0);
+            if (s->gzhead->hcrc && s->pending > beg)
+                strm->adler = crc32(strm->adler, s->pending_buf + beg,
+                                    s->pending - beg);
+            if (val == 0)
+                s->status = HCRC_STATE;
+        }
+        else
+            s->status = HCRC_STATE;
+    }
+    if (s->status == HCRC_STATE) {
+        if (s->gzhead->hcrc) {
+            if (s->pending + 2 > s->pending_buf_size)
+                flush_pending(strm);
+            if (s->pending + 2 <= s->pending_buf_size) {
+                put_byte(s, (Byte)(strm->adler & 0xff));
+                put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+                strm->adler = crc32(0L, Z_NULL, 0);
+                s->status = BUSY_STATE;
+            }
+        }
+        else
+            s->status = BUSY_STATE;
+    }
+#endif
+
+    /* Flush as much pending output as possible */
+    if (s->pending != 0) {
+        flush_pending(strm);
+        if (strm->avail_out == 0) {
+            /* Since avail_out is 0, deflate will be called again with
+             * more output space, but possibly with both pending and
+             * avail_in equal to zero. There won't be anything to do,
+             * but this is not an error situation so make sure we
+             * return OK instead of BUF_ERROR at next call of deflate:
+             */
+            s->last_flush = -1;
+            return Z_OK;
+        }
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
+     */
+    } else if (strm->avail_in == 0 && flush <= old_flush &&
+               flush != Z_FINISH) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* User must not provide more input after the first FINISH: */
+    if (s->status == FINISH_STATE && strm->avail_in != 0) {
+        ERR_RETURN(strm, Z_BUF_ERROR);
+    }
+
+    /* Start a new block or continue the current one.
+     */
+    if (strm->avail_in != 0 || s->lookahead != 0 ||
+        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+        block_state bstate;
+
+        bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+                    (s->strategy == Z_RLE ? deflate_rle(s, flush) :
+                        (*(configuration_table[s->level].func))(s, flush));
+
+        if (bstate == finish_started || bstate == finish_done) {
+            s->status = FINISH_STATE;
+        }
+        if (bstate == need_more || bstate == finish_started) {
+            if (strm->avail_out == 0) {
+                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+            }
+            return Z_OK;
+            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+             * of deflate should use the same flush parameter to make sure
+             * that the flush is complete. So we don't have to output an
+             * empty block here, this will be done at next call. This also
+             * ensures that for a very small output buffer, we emit at most
+             * one empty block.
+             */
+        }
+        if (bstate == block_done) {
+            if (flush == Z_PARTIAL_FLUSH) {
+                _tr_align(s);
+            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+                _tr_stored_block(s, (char*)0, 0L, 0);
+                /* For a full flush, this empty block will be recognized
+                 * as a special marker by inflate_sync().
+                 */
+                if (flush == Z_FULL_FLUSH) {
+                    CLEAR_HASH(s);             /* forget history */
+                    if (s->lookahead == 0) {
+                        s->strstart = 0;
+                        s->block_start = 0L;
+                    }
+                }
+            }
+            flush_pending(strm);
+            if (strm->avail_out == 0) {
+              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+              return Z_OK;
+            }
+        }
+    }
+    Assert(strm->avail_out > 0, "bug2");
+
+    if (flush != Z_FINISH) return Z_OK;
+    if (s->wrap <= 0) return Z_STREAM_END;
+
+    /* Write the trailer */
+#ifdef GZIP
+    if (s->wrap == 2) {
+        put_byte(s, (Byte)(strm->adler & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+        put_byte(s, (Byte)(strm->total_in & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+    }
+    else
+#endif
+    {
+        putShortMSB(s, (uInt)(strm->adler >> 16));
+        putShortMSB(s, (uInt)(strm->adler & 0xffff));
+    }
+    flush_pending(strm);
+    /* If avail_out is zero, the application will call deflate again
+     * to flush the rest.
+     */
+    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+    z_streamp strm;
+{
+    int status;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+    status = strm->state->status;
+    if (status != INIT_STATE &&
+        status != EXTRA_STATE &&
+        status != NAME_STATE &&
+        status != COMMENT_STATE &&
+        status != HCRC_STATE &&
+        status != BUSY_STATE &&
+        status != FINISH_STATE) {
+      return Z_STREAM_ERROR;
+    }
+
+    /* Deallocate in reverse order of allocations: */
+    TRY_FREE(strm, strm->state->pending_buf);
+    TRY_FREE(strm, strm->state->head);
+    TRY_FREE(strm, strm->state->prev);
+    TRY_FREE(strm, strm->state->window);
+
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+
+    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+    z_streamp dest;
+    z_streamp source;
+{
+#ifdef MAXSEG_64K
+    return Z_STREAM_ERROR;
+#else
+    deflate_state *ds;
+    deflate_state *ss;
+    ushf *overlay;
+
+
+    if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+        return Z_STREAM_ERROR;
+    }
+
+    ss = source->state;
+
+    zmemcpy(dest, source, sizeof(z_stream));
+
+    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    if (ds == Z_NULL) return Z_MEM_ERROR;
+    dest->state = (struct internal_state FAR *) ds;
+    zmemcpy(ds, ss, sizeof(deflate_state));
+    ds->strm = dest;
+
+    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
+    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
+    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+    ds->pending_buf = (uchf *) overlay;
+
+    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+        ds->pending_buf == Z_NULL) {
+        deflateEnd (dest);
+        return Z_MEM_ERROR;
+    }
+    /* following zmemcpy do not work for 16-bit MSDOS */
+    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+    ds->l_desc.dyn_tree = ds->dyn_ltree;
+    ds->d_desc.dyn_tree = ds->dyn_dtree;
+    ds->bl_desc.dyn_tree = ds->bl_tree;
+
+    return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+    z_streamp strm;
+    Bytef *buf;
+    unsigned size;
+{
+    unsigned len = strm->avail_in;
+
+    if (len > size) len = size;
+    if (len == 0) return 0;
+
+    strm->avail_in  -= len;
+
+    if (strm->state->wrap == 1) {
+        strm->adler = adler32(strm->adler, strm->next_in, len);
+    }
+#ifdef GZIP
+    else if (strm->state->wrap == 2) {
+        strm->adler = crc32(strm->adler, strm->next_in, len);
+    }
+#endif
+    zmemcpy(buf, strm->next_in, len);
+    strm->next_in  += len;
+    strm->total_in += len;
+
+    return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+    deflate_state *s;
+{
+    s->window_size = (ulg)2L*s->w_size;
+
+    CLEAR_HASH(s);
+
+    /* Set the default configuration parameters:
+     */
+    s->max_lazy_match   = configuration_table[s->level].max_lazy;
+    s->good_match       = configuration_table[s->level].good_length;
+    s->nice_match       = configuration_table[s->level].nice_length;
+    s->max_chain_length = configuration_table[s->level].max_chain;
+
+    s->strstart = 0;
+    s->block_start = 0L;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+    match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    unsigned chain_length = s->max_chain_length;/* max hash chain length */
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    int best_len = s->prev_length;              /* best match length so far */
+    int nice_match = s->nice_match;             /* stop if match long enough */
+    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+        s->strstart - (IPos)MAX_DIST(s) : NIL;
+    /* Stop when cur_match becomes <= limit. To simplify the code,
+     * we prevent matches with the string of window index 0.
+     */
+    Posf *prev = s->prev;
+    uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+    /* Compare two bytes at a time. Note: this is not always beneficial.
+     * Try with and without -DUNALIGNED_OK to check.
+     */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+    register ush scan_start = *(ushf*)scan;
+    register ush scan_end   = *(ushf*)(scan+best_len-1);
+#else
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+    register Byte scan_end1  = scan[best_len-1];
+    register Byte scan_end   = scan[best_len];
+#endif
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    /* Do not waste too much time if we already have a good match: */
+    if (s->prev_length >= s->good_match) {
+        chain_length >>= 2;
+    }
+    /* Do not look for matches beyond the end of the input. This is necessary
+     * to make deflate deterministic.
+     */
+    if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    do {
+        Assert(cur_match < s->strstart, "no future");
+        match = s->window + cur_match;
+
+        /* Skip to next match if the match length cannot increase
+         * or if the match length is less than 2.  Note that the checks below
+         * for insufficient lookahead only occur occasionally for performance
+         * reasons.  Therefore uninitialized memory will be accessed, and
+         * conditional jumps will be made that depend on those values.
+         * However the length of the match is limited to the lookahead, so
+         * the output of deflate is not affected by the uninitialized values.
+         */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+        /* This code assumes sizeof(unsigned short) == 2. Do not use
+         * UNALIGNED_OK if your compiler uses a different size.
+         */
+        if (*(ushf*)(match+best_len-1) != scan_end ||
+            *(ushf*)match != scan_start) continue;
+
+        /* It is not necessary to compare scan[2] and match[2] since they are
+         * always equal when the other bytes match, given that the hash keys
+         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+         * strstart+3, +5, ... up to strstart+257. We check for insufficient
+         * lookahead only every 4th comparison; the 128th check will be made
+         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+         * necessary to put more guard bytes at the end of the window, or
+         * to check more often for insufficient lookahead.
+         */
+        Assert(scan[2] == match[2], "scan[2]?");
+        scan++, match++;
+        do {
+        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+                 scan < strend);
+        /* The funny "do {}" generates better code on most compilers */
+
+        /* Here, scan <= window+strstart+257 */
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+        if (*scan == *match) scan++;
+
+        len = (MAX_MATCH - 1) - (int)(strend-scan);
+        scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+        if (match[best_len]   != scan_end  ||
+            match[best_len-1] != scan_end1 ||
+            *match            != *scan     ||
+            *++match          != scan[1])      continue;
+
+        /* The check at best_len-1 can be removed because it will be made
+         * again later. (This heuristic is not always a win.)
+         * It is not necessary to compare scan[2] and match[2] since they
+         * are always equal when the other bytes match, given that
+         * the hash keys are equal and that HASH_BITS >= 8.
+         */
+        scan += 2, match++;
+        Assert(*scan == *match, "match[2]?");
+
+        /* We check for insufficient lookahead only every 8th comparison;
+         * the 256th check will be made at strstart+258.
+         */
+        do {
+        } while (*++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 *++scan == *++match && *++scan == *++match &&
+                 scan < strend);
+
+        Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+        len = MAX_MATCH - (int)(strend - scan);
+        scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+        if (len > best_len) {
+            s->match_start = cur_match;
+            best_len = len;
+            if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+            scan_end = *(ushf*)(scan+best_len-1);
+#else
+            scan_end1  = scan[best_len-1];
+            scan_end   = scan[best_len];
+#endif
+        }
+    } while ((cur_match = prev[cur_match & wmask]) > limit
+             && --chain_length != 0);
+
+    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+    return s->lookahead;
+}
+#endif /* ASMV */
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(s, cur_match)
+    deflate_state *s;
+    IPos cur_match;                             /* current match */
+{
+    register Bytef *scan = s->window + s->strstart; /* current string */
+    register Bytef *match;                       /* matched string */
+    register int len;                           /* length of current match */
+    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+     * It is easy to get rid of this optimization if necessary.
+     */
+    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+    Assert(cur_match < s->strstart, "no future");
+
+    match = s->window + cur_match;
+
+    /* Return failure if the match length is less than 2:
+     */
+    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2, match += 2;
+    Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+    } while (*++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             *++scan == *++match && *++scan == *++match &&
+             scan < strend);
+
+    Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (int)(strend - scan);
+
+    if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+    s->match_start = cur_match;
+    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+    deflate_state *s;
+    IPos start, match;
+    int length;
+{
+    /* check that the match is indeed a match */
+    if (zmemcmp(s->window + match,
+                s->window + start, length) != EQUAL) {
+        fprintf(stderr, " start %u, match %u, length %d\n",
+                start, match, length);
+        do {
+            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+        } while (--length != 0);
+        z_error("invalid match");
+    }
+    if (z_verbose > 1) {
+        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        do { putc(s->window[start++], stderr); } while (--length != 0);
+    }
+}
+#else
+#  define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+local void fill_window(s)
+    deflate_state *s;
+{
+    register unsigned n, m;
+    register Posf *p;
+    unsigned more;    /* Amount of free space at the end of the window. */
+    uInt wsize = s->w_size;
+
+    do {
+        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+        /* Deal with !@#$% 64K limit: */
+        if (sizeof(int) <= 2) {
+            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+                more = wsize;
+
+            } else if (more == (unsigned)(-1)) {
+                /* Very unlikely, but possible on 16 bit machine if
+                 * strstart == 0 && lookahead == 1 (input done a byte at time)
+                 */
+                more--;
+            }
+        }
+
+        /* If the window is almost full and there is insufficient lookahead,
+         * move the upper half to the lower one to make room in the upper half.
+         */
+        if (s->strstart >= wsize+MAX_DIST(s)) {
+
+            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+            s->match_start -= wsize;
+            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
+            s->block_start -= (long) wsize;
+
+            /* Slide the hash table (could be avoided with 32 bit values
+               at the expense of memory usage). We slide even when level == 0
+               to keep the hash table consistent if we switch back to level > 0
+               later. (Using level 0 permanently is not an optimal usage of
+               zlib, so we don't care about this pathological case.)
+             */
+            n = s->hash_size;
+            p = &s->head[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+            } while (--n);
+
+            n = wsize;
+#ifndef FASTEST
+            p = &s->prev[n];
+            do {
+                m = *--p;
+                *p = (Pos)(m >= wsize ? m-wsize : NIL);
+                /* If n is not on any hash chain, prev[n] is garbage but
+                 * its value will never be used.
+                 */
+            } while (--n);
+#endif
+            more += wsize;
+        }
+        if (s->strm->avail_in == 0) return;
+
+        /* If there was no sliding:
+         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+         *    more == window_size - lookahead - strstart
+         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+         * => more >= window_size - 2*WSIZE + 2
+         * In the BIG_MEM or MMAP case (not yet supported),
+         *   window_size == input_size + MIN_LOOKAHEAD  &&
+         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+         * Otherwise, window_size == 2*WSIZE so more >= 2.
+         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+         */
+        Assert(more >= 2, "more < 2");
+
+        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+        s->lookahead += n;
+
+        /* Initialize the hash value now that we have some input: */
+        if (s->lookahead >= MIN_MATCH) {
+            s->ins_h = s->window[s->strstart];
+            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+            Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+        }
+        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+         * but this is not important since only literal bytes will be emitted.
+         */
+
+    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+    /* If the WIN_INIT bytes after the end of the current data have never been
+     * written, then zero those bytes in order to avoid memory check reports of
+     * the use of uninitialized (or uninitialised as Julian writes) bytes by
+     * the longest match routines.  Update the high water mark for the next
+     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
+     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+     */
+    if (s->high_water < s->window_size) {
+        ulg curr = s->strstart + (ulg)(s->lookahead);
+        ulg init;
+
+        if (s->high_water < curr) {
+            /* Previous high water mark below current data -- zero WIN_INIT
+             * bytes or up to end of window, whichever is less.
+             */
+            init = s->window_size - curr;
+            if (init > WIN_INIT)
+                init = WIN_INIT;
+            zmemzero(s->window + curr, (unsigned)init);
+            s->high_water = curr + init;
+        }
+        else if (s->high_water < (ulg)curr + WIN_INIT) {
+            /* High water mark at or above current data, but below current data
+             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+             * to end of window, whichever is less.
+             */
+            init = (ulg)curr + WIN_INIT - s->high_water;
+            if (init > s->window_size - s->high_water)
+                init = s->window_size - s->high_water;
+            zmemzero(s->window + s->high_water, (unsigned)init);
+            s->high_water += init;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+   _tr_flush_block(s, (s->block_start >= 0L ? \
+                   (charf *)&s->window[(unsigned)s->block_start] : \
+                   (charf *)Z_NULL), \
+                (ulg)((long)s->strstart - s->block_start), \
+                (last)); \
+   s->block_start = s->strstart; \
+   flush_pending(s->strm); \
+   Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+   FLUSH_BLOCK_ONLY(s, last); \
+   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+     * to pending_buf_size, and each stored block has a 5 byte header:
+     */
+    ulg max_block_size = 0xffff;
+    ulg max_start;
+
+    if (max_block_size > s->pending_buf_size - 5) {
+        max_block_size = s->pending_buf_size - 5;
+    }
+
+    /* Copy as much as possible from input to output: */
+    for (;;) {
+        /* Fill the window as much as possible: */
+        if (s->lookahead <= 1) {
+
+            Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+                   s->block_start >= (long)s->w_size, "slide too late");
+
+            fill_window(s);
+            if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+        Assert(s->block_start >= 0L, "block gone");
+
+        s->strstart += s->lookahead;
+        s->lookahead = 0;
+
+        /* Emit a stored block if pending_buf will be full: */
+        max_start = s->block_start + max_block_size;
+        if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+            /* strstart == 0 is possible when wraparound on 16-bit machine */
+            s->lookahead = (uInt)(s->strstart - max_start);
+            s->strstart = (uInt)max_start;
+            FLUSH_BLOCK(s, 0);
+        }
+        /* Flush if we may have to slide, otherwise block_start may become
+         * negative and the data will be gone:
+         */
+        if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+            FLUSH_BLOCK(s, 0);
+        }
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head;       /* head of the hash chain */
+    int bflush;           /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        hash_head = NIL;
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         * At this point we have always match_length < MIN_MATCH
+         */
+        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
+        }
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->match_start, s->match_length);
+
+            _tr_tally_dist(s, s->strstart - s->match_start,
+                           s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+
+            /* Insert new strings in the hash table only if the match length
+             * is not too large. This saves time but degrades compression.
+             */
+#ifndef FASTEST
+            if (s->match_length <= s->max_insert_length &&
+                s->lookahead >= MIN_MATCH) {
+                s->match_length--; /* string at strstart already in table */
+                do {
+                    s->strstart++;
+                    INSERT_STRING(s, s->strstart, hash_head);
+                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                     * always MIN_MATCH bytes ahead.
+                     */
+                } while (--s->match_length != 0);
+                s->strstart++;
+            } else
+#endif
+            {
+                s->strstart += s->match_length;
+                s->match_length = 0;
+                s->ins_h = s->window[s->strstart];
+                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+                Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                 * matter since it will be recomputed at next deflate call.
+                 */
+            }
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    IPos hash_head;          /* head of hash chain */
+    int bflush;              /* set if current block must be flushed */
+
+    /* Process the input block. */
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the next match, plus MIN_MATCH bytes to insert the
+         * string following the next match.
+         */
+        if (s->lookahead < MIN_LOOKAHEAD) {
+            fill_window(s);
+            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* Insert the string window[strstart .. strstart+2] in the
+         * dictionary, and set hash_head to the head of the hash chain:
+         */
+        hash_head = NIL;
+        if (s->lookahead >= MIN_MATCH) {
+            INSERT_STRING(s, s->strstart, hash_head);
+        }
+
+        /* Find the longest match, discarding those <= prev_length.
+         */
+        s->prev_length = s->match_length, s->prev_match = s->match_start;
+        s->match_length = MIN_MATCH-1;
+
+        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+            s->strstart - hash_head <= MAX_DIST(s)) {
+            /* To simplify the code, we prevent matches with the string
+             * of window index 0 (in particular we have to avoid a match
+             * of the string with itself at the start of the input file).
+             */
+            s->match_length = longest_match (s, hash_head);
+            /* longest_match() sets match_start */
+
+            if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+                || (s->match_length == MIN_MATCH &&
+                    s->strstart - s->match_start > TOO_FAR)
+#endif
+                )) {
+
+                /* If prev_match is also MIN_MATCH, match_start is garbage
+                 * but we will ignore the current match anyway.
+                 */
+                s->match_length = MIN_MATCH-1;
+            }
+        }
+        /* If there was a match at the previous step and the current
+         * match is not better, output the previous match:
+         */
+        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+            /* Do not insert strings in hash table beyond this. */
+
+            check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+                           s->prev_length - MIN_MATCH, bflush);
+
+            /* Insert in hash table all strings up to the end of the match.
+             * strstart-1 and strstart are already inserted. If there is not
+             * enough lookahead, the last two strings are not inserted in
+             * the hash table.
+             */
+            s->lookahead -= s->prev_length-1;
+            s->prev_length -= 2;
+            do {
+                if (++s->strstart <= max_insert) {
+                    INSERT_STRING(s, s->strstart, hash_head);
+                }
+            } while (--s->prev_length != 0);
+            s->match_available = 0;
+            s->match_length = MIN_MATCH-1;
+            s->strstart++;
+
+            if (bflush) FLUSH_BLOCK(s, 0);
+
+        } else if (s->match_available) {
+            /* If there was no match at the previous position, output a
+             * single literal. If there was a match but the current match
+             * is longer, truncate the previous match to a single literal.
+             */
+            Tracevv((stderr,"%c", s->window[s->strstart-1]));
+            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+            if (bflush) {
+                FLUSH_BLOCK_ONLY(s, 0);
+            }
+            s->strstart++;
+            s->lookahead--;
+            if (s->strm->avail_out == 0) return need_more;
+        } else {
+            /* There is no previous match to compare with, wait for
+             * the next step to decide.
+             */
+            s->match_available = 1;
+            s->strstart++;
+            s->lookahead--;
+        }
+    }
+    Assert (flush != Z_NO_FLUSH, "no flush?");
+    if (s->match_available) {
+        Tracevv((stderr,"%c", s->window[s->strstart-1]));
+        _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+        s->match_available = 0;
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one.  Do not maintain a hash table.  (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;             /* set if current block must be flushed */
+    uInt prev;              /* byte at distance one to match */
+    Bytef *scan, *strend;   /* scan goes up to strend for length of run */
+
+    for (;;) {
+        /* Make sure that we always have enough lookahead, except
+         * at the end of the input file. We need MAX_MATCH bytes
+         * for the longest encodable run.
+         */
+        if (s->lookahead < MAX_MATCH) {
+            fill_window(s);
+            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+                return need_more;
+            }
+            if (s->lookahead == 0) break; /* flush the current block */
+        }
+
+        /* See how many times the previous byte repeats */
+        s->match_length = 0;
+        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+            scan = s->window + s->strstart - 1;
+            prev = *scan;
+            if (prev == *++scan && prev == *++scan && prev == *++scan) {
+                strend = s->window + s->strstart + MAX_MATCH;
+                do {
+                } while (prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         prev == *++scan && prev == *++scan &&
+                         scan < strend);
+                s->match_length = MAX_MATCH - (int)(strend - scan);
+                if (s->match_length > s->lookahead)
+                    s->match_length = s->lookahead;
+            }
+        }
+
+        /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+        if (s->match_length >= MIN_MATCH) {
+            check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+            s->lookahead -= s->match_length;
+            s->strstart += s->match_length;
+            s->match_length = 0;
+        } else {
+            /* No match, output a literal byte */
+            Tracevv((stderr,"%c", s->window[s->strstart]));
+            _tr_tally_lit (s, s->window[s->strstart], bflush);
+            s->lookahead--;
+            s->strstart++;
+        }
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(s, flush)
+    deflate_state *s;
+    int flush;
+{
+    int bflush;             /* set if current block must be flushed */
+
+    for (;;) {
+        /* Make sure that we have a literal to write. */
+        if (s->lookahead == 0) {
+            fill_window(s);
+            if (s->lookahead == 0) {
+                if (flush == Z_NO_FLUSH)
+                    return need_more;
+                break;      /* flush the current block */
+            }
+        }
+
+        /* Output a literal byte */
+        s->match_length = 0;
+        Tracevv((stderr,"%c", s->window[s->strstart]));
+        _tr_tally_lit (s, s->window[s->strstart], bflush);
+        s->lookahead--;
+        s->strstart++;
+        if (bflush) FLUSH_BLOCK(s, 0);
+    }
+    FLUSH_BLOCK(s, flush == Z_FINISH);
+    return flush == Z_FINISH ? finish_done : block_done;
+}
diff --git a/libgit2/deps/zlib/deflate.h b/libgit2/deps/zlib/deflate.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/deflate.h
@@ -0,0 +1,342 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2010 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer creation by deflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip encoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS  256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES   30
+/* number of distance codes */
+
+#define BL_CODES  19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE    42
+#define EXTRA_STATE   69
+#define NAME_STATE    73
+#define COMMENT_STATE 91
+#define HCRC_STATE   103
+#define BUSY_STATE   113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+    union {
+        ush  freq;       /* frequency count */
+        ush  code;       /* bit string */
+    } fc;
+    union {
+        ush  dad;        /* father node in Huffman tree */
+        ush  len;        /* length of bit string */
+    } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad  dl.dad
+#define Len  dl.len
+
+typedef struct static_tree_desc_s  static_tree_desc;
+
+typedef struct tree_desc_s {
+    ct_data *dyn_tree;           /* the dynamic tree */
+    int     max_code;            /* largest code with non zero frequency */
+    static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+    z_streamp strm;      /* pointer back to this zlib stream */
+    int   status;        /* as the name implies */
+    Bytef *pending_buf;  /* output still pending */
+    ulg   pending_buf_size; /* size of pending_buf */
+    Bytef *pending_out;  /* next pending byte to output to the stream */
+    uInt   pending;      /* nb of bytes in the pending buffer */
+    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
+    gz_headerp  gzhead;  /* gzip header information to write */
+    uInt   gzindex;      /* where in extra, name, or comment */
+    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    int   last_flush;    /* value of flush param for previous deflate call */
+
+                /* used by deflate.c: */
+
+    uInt  w_size;        /* LZ77 window size (32K by default) */
+    uInt  w_bits;        /* log2(w_size)  (8..16) */
+    uInt  w_mask;        /* w_size - 1 */
+
+    Bytef *window;
+    /* Sliding window. Input bytes are read into the second half of the window,
+     * and move to the first half later to keep a dictionary of at least wSize
+     * bytes. With this organization, matches are limited to a distance of
+     * wSize-MAX_MATCH bytes, but this ensures that IO is always
+     * performed with a length multiple of the block size. Also, it limits
+     * the window size to 64K, which is quite useful on MSDOS.
+     * To do: use the user input buffer as sliding window.
+     */
+
+    ulg window_size;
+    /* Actual size of window: 2*wSize, except when the user input buffer
+     * is directly used as sliding window.
+     */
+
+    Posf *prev;
+    /* Link to older string with same hash index. To limit the size of this
+     * array to 64K, this link is maintained only for the last 32K strings.
+     * An index in this array is thus a window index modulo 32K.
+     */
+
+    Posf *head; /* Heads of the hash chains or NIL. */
+
+    uInt  ins_h;          /* hash index of string to be inserted */
+    uInt  hash_size;      /* number of elements in hash table */
+    uInt  hash_bits;      /* log2(hash_size) */
+    uInt  hash_mask;      /* hash_size-1 */
+
+    uInt  hash_shift;
+    /* Number of bits by which ins_h must be shifted at each input
+     * step. It must be such that after MIN_MATCH steps, the oldest
+     * byte no longer takes part in the hash key, that is:
+     *   hash_shift * MIN_MATCH >= hash_bits
+     */
+
+    long block_start;
+    /* Window position at the beginning of the current output block. Gets
+     * negative when the window is moved backwards.
+     */
+
+    uInt match_length;           /* length of best match */
+    IPos prev_match;             /* previous match */
+    int match_available;         /* set if previous match exists */
+    uInt strstart;               /* start of string to insert */
+    uInt match_start;            /* start of matching string */
+    uInt lookahead;              /* number of valid bytes ahead in window */
+
+    uInt prev_length;
+    /* Length of the best match at previous step. Matches not greater than this
+     * are discarded. This is used in the lazy match evaluation.
+     */
+
+    uInt max_chain_length;
+    /* To speed up deflation, hash chains are never searched beyond this
+     * length.  A higher limit improves compression ratio but degrades the
+     * speed.
+     */
+
+    uInt max_lazy_match;
+    /* Attempt to find a better match only when the current match is strictly
+     * smaller than this value. This mechanism is used only for compression
+     * levels >= 4.
+     */
+#   define max_insert_length  max_lazy_match
+    /* Insert new strings in the hash table only if the match length is not
+     * greater than this length. This saves time but degrades compression.
+     * max_insert_length is used only for compression levels <= 3.
+     */
+
+    int level;    /* compression level (1..9) */
+    int strategy; /* favor or force Huffman coding*/
+
+    uInt good_match;
+    /* Use a faster search when the previous match is longer than this */
+
+    int nice_match; /* Stop searching when current match exceeds this */
+
+                /* used by trees.c: */
+    /* Didn't use ct_data typedef below to supress compiler warning */
+    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+    struct tree_desc_s l_desc;               /* desc. for literal tree */
+    struct tree_desc_s d_desc;               /* desc. for distance tree */
+    struct tree_desc_s bl_desc;              /* desc. for bit length tree */
+
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+    int heap_len;               /* number of elements in the heap */
+    int heap_max;               /* element of largest frequency */
+    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+     * The same heap array is used to build all trees.
+     */
+
+    uch depth[2*L_CODES+1];
+    /* Depth of each subtree used as tie breaker for trees of equal frequency
+     */
+
+    uchf *l_buf;          /* buffer for literals or lengths */
+
+    uInt  lit_bufsize;
+    /* Size of match buffer for literals/lengths.  There are 4 reasons for
+     * limiting lit_bufsize to 64K:
+     *   - frequencies can be kept in 16 bit counters
+     *   - if compression is not successful for the first block, all input
+     *     data is still in the window so we can still emit a stored block even
+     *     when input comes from standard input.  (This can also be done for
+     *     all blocks if lit_bufsize is not greater than 32K.)
+     *   - if compression is not successful for a file smaller than 64K, we can
+     *     even emit a stored file instead of a stored block (saving 5 bytes).
+     *     This is applicable only for zip (not gzip or zlib).
+     *   - creating new Huffman trees less frequently may not provide fast
+     *     adaptation to changes in the input data statistics. (Take for
+     *     example a binary file with poorly compressible code followed by
+     *     a highly compressible string table.) Smaller buffer sizes give
+     *     fast adaptation but have of course the overhead of transmitting
+     *     trees more frequently.
+     *   - I can't count above 4
+     */
+
+    uInt last_lit;      /* running index in l_buf */
+
+    ushf *d_buf;
+    /* Buffer for distances. To simplify the code, d_buf and l_buf have
+     * the same number of elements. To use different lengths, an extra flag
+     * array would be necessary.
+     */
+
+    ulg opt_len;        /* bit length of current block with optimal trees */
+    ulg static_len;     /* bit length of current block with static trees */
+    uInt matches;       /* number of string matches in current block */
+    int last_eob_len;   /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+    ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */
+#endif
+
+    ush bi_buf;
+    /* Output buffer. bits are inserted starting at the bottom (least
+     * significant bits).
+     */
+    int bi_valid;
+    /* Number of valid bits in bi_buf.  All bits above the last valid bit
+     * are always zero.
+     */
+
+    ulg high_water;
+    /* High water mark offset in window for initialized bytes -- bytes above
+     * this are set to zero in order to avoid memory check warnings when
+     * longest match routines access bytes past the input.  This is then
+     * updated to the new high water mark.
+     */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+   memory checker errors from longest match routines */
+
+        /* in trees.c */
+void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
+int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
+void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+                        ulg stored_len, int last));
+
+#define d_code(dist) \
+   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+  extern uch ZLIB_INTERNAL _length_code[];
+  extern uch ZLIB_INTERNAL _dist_code[];
+#else
+  extern const uch ZLIB_INTERNAL _length_code[];
+  extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+  { uch cc = (uch)(c); \
+    s->d_buf[s->last_lit] = 0; \
+    s->l_buf[s->last_lit++] = cc; \
+    s->dyn_ltree[cc].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+   }
+# define _tr_tally_dist(s, distance, length, flush) \
+  { uch len = (uch)(length); \
+    ush dist = (ush)(distance); \
+    s->d_buf[s->last_lit] = dist; \
+    s->l_buf[s->last_lit++] = len; \
+    dist--; \
+    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+    s->dyn_dtree[d_code(dist)].Freq++; \
+    flush = (s->last_lit == s->lit_bufsize-1); \
+  }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+              flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/libgit2/deps/zlib/inffast.c b/libgit2/deps/zlib/inffast.c
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/inffast.c
@@ -0,0 +1,340 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2008, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+   Based on testing to date,
+   Pre-increment preferred for:
+   - PowerPC G3 (Adler)
+   - MIPS R5000 (Randers-Pehrson)
+   Post-increment preferred for:
+   - none
+   No measurable difference:
+   - Pentium III (Anderson)
+   - M68060 (Nikl)
+ */
+#ifdef POSTINC
+#  define OFF 0
+#  define PUP(a) *(a)++
+#else
+#  define OFF 1
+#  define PUP(a) *++(a)
+#endif
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+void ZLIB_INTERNAL inflate_fast(strm, start)
+z_streamp strm;
+unsigned start;         /* inflate()'s starting value for strm->avail_out */
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *in;      /* local strm->next_in */
+    unsigned char FAR *last;    /* while in < last, enough input available */
+    unsigned char FAR *out;     /* local strm->next_out */
+    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char FAR *end;     /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const FAR *lcode;      /* local strm->lencode */
+    code const FAR *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code here;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char FAR *from;    /* where to copy match from */
+
+    /* copy state to local variables */
+    state = (struct inflate_state FAR *)strm->state;
+    in = strm->next_in - OFF;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out - OFF;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    wnext = state->wnext;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
+
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
+    do {
+        if (bits < 15) {
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+        }
+        here = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(here.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(here.op);
+        if (op == 0) {                          /* literal */
+            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                    "inflate:         literal '%c'\n" :
+                    "inflate:         literal 0x%02x\n", here.val));
+            PUP(out) = (unsigned char)(here.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(here.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", len));
+            if (bits < 15) {
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+            }
+            here = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(here.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(here.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(here.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(PUP(in)) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                Tracevv((stderr, "inflate:         distance %u\n", dist));
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        if (state->sane) {
+                            strm->msg =
+                                (char *)"invalid distance too far back";
+                            state->mode = BAD;
+                            break;
+                        }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                        if (len <= op - whave) {
+                            do {
+                                PUP(out) = 0;
+                            } while (--len);
+                            continue;
+                        }
+                        len -= op - whave;
+                        do {
+                            PUP(out) = 0;
+                        } while (--op > whave);
+                        if (op == 0) {
+                            from = out - dist;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--len);
+                            continue;
+                        }
+#endif
+                    }
+                    from = window - OFF;
+                    if (wnext == 0) {           /* very common case */
+                        from += wsize - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    else if (wnext < op) {      /* wrap around window */
+                        from += wsize + wnext - op;
+                        op -= wnext;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = window - OFF;
+                            if (wnext < len) {  /* some from start of window */
+                                op = wnext;
+                                len -= op;
+                                do {
+                                    PUP(out) = PUP(from);
+                                } while (--op);
+                                from = out - dist;      /* rest from output */
+                            }
+                        }
+                    }
+                    else {                      /* contiguous in window */
+                        from += wnext - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    while (len > 2) {
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    }
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+                else {
+                    from = out - dist;          /* copy direct from output */
+                    do {                        /* minimum length is three */
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    } while (len > 2);
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                here = dcode[here.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            here = lcode[here.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            Tracevv((stderr, "inflate:         end of block\n"));
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
+
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in + OFF;
+    strm->next_out = out + OFF;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
+}
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and wnext == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/libgit2/deps/zlib/inffast.h b/libgit2/deps/zlib/inffast.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/libgit2/deps/zlib/inffixed.h b/libgit2/deps/zlib/inffixed.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/inffixed.h
@@ -0,0 +1,94 @@
+    /* inffixed.h -- table for decoding fixed codes
+     * Generated automatically by makefixed().
+     */
+
+    /* WARNING: this file should *not* be used by applications. It
+       is part of the implementation of the compression library and
+       is subject to change. Applications should only use zlib.h.
+     */
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+        {0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+        {22,5,193},{64,5,0}
+    };
diff --git a/libgit2/deps/zlib/inflate.c b/libgit2/deps/zlib/inflate.c
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/inflate.c
@@ -0,0 +1,1480 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0    24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ *   creation of window when not needed, minimize use of window when it is
+ *   needed, make inffast.c even faster, implement gzip decoding, and to
+ *   improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1    25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2    4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ *   to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3    22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ *   buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4    1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ *   source file infback.c to provide a call-back interface to inflate for
+ *   programs like gzip and unzip -- uses window as output buffer to avoid
+ *   window copying
+ *
+ * 1.2.beta5    1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ *   input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6    4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ *   make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7    27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0        9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ *   for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ *   and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+#  ifndef BUILDFIXED
+#    define BUILDFIXED
+#  endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+   void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+                              unsigned len));
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = Z_NULL;
+    strm->adler = 1;        /* to support ill-conceived Java test suite */
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->head = Z_NULL;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+    state->sane = 1;
+    state->back = -1;
+    Tracev((stderr, "inflate: reset\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateReset2(strm, windowBits)
+z_streamp strm;
+int windowBits;
+{
+    int wrap;
+    struct inflate_state FAR *state;
+
+    /* get the state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* extract wrap request from windowBits parameter */
+    if (windowBits < 0) {
+        wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+        if (windowBits < 48)
+            windowBits &= 15;
+#endif
+    }
+
+    /* set number of window bits, free window if different */
+    if (windowBits && (windowBits < 8 || windowBits > 15))
+        return Z_STREAM_ERROR;
+    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+        ZFREE(strm, state->window);
+        state->window = Z_NULL;
+    }
+
+    /* update state and reset the rest of it */
+    state->wrap = wrap;
+    state->wbits = (unsigned)windowBits;
+    return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+    int ret;
+    struct inflate_state FAR *state;
+
+    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+        stream_size != (int)(sizeof(z_stream)))
+        return Z_VERSION_ERROR;
+    if (strm == Z_NULL) return Z_STREAM_ERROR;
+    strm->msg = Z_NULL;                 /* in case we return an error */
+    if (strm->zalloc == (alloc_func)0) {
+        strm->zalloc = zcalloc;
+        strm->opaque = (voidpf)0;
+    }
+    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    state = (struct inflate_state FAR *)
+            ZALLOC(strm, 1, sizeof(struct inflate_state));
+    if (state == Z_NULL) return Z_MEM_ERROR;
+    Tracev((stderr, "inflate: allocated\n"));
+    strm->state = (struct internal_state FAR *)state;
+    state->window = Z_NULL;
+    ret = inflateReset2(strm, windowBits);
+    if (ret != Z_OK) {
+        ZFREE(strm, state);
+        strm->state = Z_NULL;
+    }
+    return ret;
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (bits < 0) {
+        state->hold = 0;
+        state->bits = 0;
+        return Z_OK;
+    }
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+   If BUILDFIXED is defined, then instead this routine builds the tables the
+   first time it's called, and returns those tables the first time and
+   thereafter.  This reduces the size of the code by about 2K bytes, in
+   exchange for a little execution time.  However, BUILDFIXED should not be
+   used for threaded applications, since the rewriting of the tables and virgin
+   may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+    static int virgin = 1;
+    static code *lenfix, *distfix;
+    static code fixed[544];
+
+    /* build fixed huffman tables if first call (may not be thread safe) */
+    if (virgin) {
+        unsigned sym, bits;
+        static code *next;
+
+        /* literal/length table */
+        sym = 0;
+        while (sym < 144) state->lens[sym++] = 8;
+        while (sym < 256) state->lens[sym++] = 9;
+        while (sym < 280) state->lens[sym++] = 7;
+        while (sym < 288) state->lens[sym++] = 8;
+        next = fixed;
+        lenfix = next;
+        bits = 9;
+        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+        /* distance table */
+        sym = 0;
+        while (sym < 32) state->lens[sym++] = 5;
+        distfix = next;
+        bits = 5;
+        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+        /* do this just once */
+        virgin = 0;
+    }
+#else /* !BUILDFIXED */
+#   include "inffixed.h"
+#endif /* BUILDFIXED */
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also
+   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes
+   those tables to stdout, which would be piped to inffixed.h.  A small program
+   can simply call makefixed to do this:
+
+    void makefixed(void);
+
+    int main(void)
+    {
+        makefixed();
+        return 0;
+    }
+
+   Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+    a.out > inffixed.h
+ */
+void makefixed()
+{
+    unsigned low, size;
+    struct inflate_state state;
+
+    fixedtables(&state);
+    puts("    /* inffixed.h -- table for decoding fixed codes");
+    puts("     * Generated automatically by makefixed().");
+    puts("     */");
+    puts("");
+    puts("    /* WARNING: this file should *not* be used by applications.");
+    puts("       It is part of the implementation of this library and is");
+    puts("       subject to change. Applications should only use zlib.h.");
+    puts("     */");
+    puts("");
+    size = 1U << 9;
+    printf("    static const code lenfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 7) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+               state.lencode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+    size = 1U << 5;
+    printf("\n    static const code distfix[%u] = {", size);
+    low = 0;
+    for (;;) {
+        if ((low % 6) == 0) printf("\n        ");
+        printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+               state.distcode[low].val);
+        if (++low == size) break;
+        putchar(',');
+    }
+    puts("\n    };");
+}
+#endif /* MAKEFIXED */
+
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning.  If window does not exist yet, create it.  This is only called
+   when a window is already in use, or when output has been written during this
+   inflate call, but the end of the deflate stream has not been reached yet.
+   It is also called to create a window for dictionary data when a dictionary
+   is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+    struct inflate_state FAR *state;
+    unsigned copy, dist;
+
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        state->window = (unsigned char FAR *)
+                        ZALLOC(strm, 1U << state->wbits,
+                               sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->wnext = 0;
+        state->whave = 0;
+    }
+
+    /* copy state->wsize or less output bytes into the circular window */
+    copy = out - strm->avail_out;
+    if (copy >= state->wsize) {
+        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+        state->wnext = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->wnext;
+        if (dist > copy) dist = copy;
+        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
+        copy -= dist;
+        if (copy) {
+            zmemcpy(state->window, strm->next_out - copy, copy);
+            state->wnext = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->wnext += dist;
+            if (state->wnext == state->wsize) state->wnext = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
+    return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+#  define UPDATE(check, buf, len) \
+    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+#  define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+#  define CRC2(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        check = crc32(check, hbuf, 2); \
+    } while (0)
+
+#  define CRC4(check, word) \
+    do { \
+        hbuf[0] = (unsigned char)(word); \
+        hbuf[1] = (unsigned char)((word) >> 8); \
+        hbuf[2] = (unsigned char)((word) >> 16); \
+        hbuf[3] = (unsigned char)((word) >> 24); \
+        check = crc32(check, hbuf, 4); \
+    } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+    struct inflate_state FAR *state;
+    unsigned char FAR *next;    /* next input */
+    unsigned char FAR *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char FAR *from;    /* where to copy match bytes from */
+    code here;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+#ifdef GUNZIP
+    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */
+#endif
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+        (strm->next_in == Z_NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+#ifdef GUNZIP
+            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */
+                state->check = crc32(0L, Z_NULL, 0);
+                CRC2(state->check, hold);
+                INITBITS();
+                state->mode = FLAGS;
+                break;
+            }
+            state->flags = 0;           /* expect zlib header */
+            if (state->head != Z_NULL)
+                state->head->done = -1;
+            if (!(state->wrap & 1) ||   /* check if zlib header allowed */
+#else
+            if (
+#endif
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (state->wbits == 0)
+                state->wbits = len;
+            else if (len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            Tracev((stderr, "inflate:   zlib header ok\n"));
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+#ifdef GUNZIP
+        case FLAGS:
+            NEEDBITS(16);
+            state->flags = (int)(hold);
+            if ((state->flags & 0xff) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            if (state->flags & 0xe000) {
+                strm->msg = (char *)"unknown header flags set";
+                state->mode = BAD;
+                break;
+            }
+            if (state->head != Z_NULL)
+                state->head->text = (int)((hold >> 8) & 1);
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = TIME;
+        case TIME:
+            NEEDBITS(32);
+            if (state->head != Z_NULL)
+                state->head->time = hold;
+            if (state->flags & 0x0200) CRC4(state->check, hold);
+            INITBITS();
+            state->mode = OS;
+        case OS:
+            NEEDBITS(16);
+            if (state->head != Z_NULL) {
+                state->head->xflags = (int)(hold & 0xff);
+                state->head->os = (int)(hold >> 8);
+            }
+            if (state->flags & 0x0200) CRC2(state->check, hold);
+            INITBITS();
+            state->mode = EXLEN;
+        case EXLEN:
+            if (state->flags & 0x0400) {
+                NEEDBITS(16);
+                state->length = (unsigned)(hold);
+                if (state->head != Z_NULL)
+                    state->head->extra_len = (unsigned)hold;
+                if (state->flags & 0x0200) CRC2(state->check, hold);
+                INITBITS();
+            }
+            else if (state->head != Z_NULL)
+                state->head->extra = Z_NULL;
+            state->mode = EXTRA;
+        case EXTRA:
+            if (state->flags & 0x0400) {
+                copy = state->length;
+                if (copy > have) copy = have;
+                if (copy) {
+                    if (state->head != Z_NULL &&
+                        state->head->extra != Z_NULL) {
+                        len = state->head->extra_len - state->length;
+                        zmemcpy(state->head->extra + len, next,
+                                len + copy > state->head->extra_max ?
+                                state->head->extra_max - len : copy);
+                    }
+                    if (state->flags & 0x0200)
+                        state->check = crc32(state->check, next, copy);
+                    have -= copy;
+                    next += copy;
+                    state->length -= copy;
+                }
+                if (state->length) goto inf_leave;
+            }
+            state->length = 0;
+            state->mode = NAME;
+        case NAME:
+            if (state->flags & 0x0800) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->name != Z_NULL &&
+                            state->length < state->head->name_max)
+                        state->head->name[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->name = Z_NULL;
+            state->length = 0;
+            state->mode = COMMENT;
+        case COMMENT:
+            if (state->flags & 0x1000) {
+                if (have == 0) goto inf_leave;
+                copy = 0;
+                do {
+                    len = (unsigned)(next[copy++]);
+                    if (state->head != Z_NULL &&
+                            state->head->comment != Z_NULL &&
+                            state->length < state->head->comm_max)
+                        state->head->comment[state->length++] = len;
+                } while (len && copy < have);
+                if (state->flags & 0x0200)
+                    state->check = crc32(state->check, next, copy);
+                have -= copy;
+                next += copy;
+                if (len) goto inf_leave;
+            }
+            else if (state->head != Z_NULL)
+                state->head->comment = Z_NULL;
+            state->mode = HCRC;
+        case HCRC:
+            if (state->flags & 0x0200) {
+                NEEDBITS(16);
+                if (hold != (state->check & 0xffff)) {
+                    strm->msg = (char *)"header crc mismatch";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            if (state->head != Z_NULL) {
+                state->head->hcrc = (int)((state->flags >> 9) & 1);
+                state->head->done = 1;
+            }
+            strm->adler = state->check = crc32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+            break;
+#endif
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = REVERSE(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = adler32(0L, Z_NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                Tracev((stderr, "inflate:     stored block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                fixedtables(state);
+                Tracev((stderr, "inflate:     fixed codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = LEN_;             /* decode codes */
+                if (flush == Z_TREES) {
+                    DROPBITS(2);
+                    goto inf_leave;
+                }
+                break;
+            case 2:                             /* dynamic block */
+                Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                        state->last ? " (last)" : ""));
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            Tracev((stderr, "inflate:       stored length %u\n",
+                    state->length));
+            INITBITS();
+            state->mode = COPY_;
+            if (flush == Z_TREES) goto inf_leave;
+        case COPY_:
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                zmemcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            Tracev((stderr, "inflate:       stored end\n"));
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracev((stderr, "inflate:       table sizes ok\n"));
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 7;
+            ret = inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       code lengths ok\n"));
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    here = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (here.val < 16) {
+                    NEEDBITS(here.bits);
+                    DROPBITS(here.bits);
+                    state->lens[state->have++] = here.val;
+                }
+                else {
+                    if (here.val == 16) {
+                        NEEDBITS(here.bits + 2);
+                        DROPBITS(here.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (here.val == 17) {
+                        NEEDBITS(here.bits + 3);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(here.bits + 7);
+                        DROPBITS(here.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* check for end-of-block code (better have one) */
+            if (state->lens[256] == 0) {
+                strm->msg = (char *)"invalid code -- missing end-of-block";
+                state->mode = BAD;
+                break;
+            }
+
+            /* build code tables -- note: do not change the lenbits or distbits
+               values here (9 and 6) without reading the comments in inftrees.h
+               concerning the ENOUGH constants, which depend on those values */
+            state->next = state->codes;
+            state->lencode = (code const FAR *)(state->next);
+            state->lenbits = 9;
+            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const FAR *)(state->next);
+            state->distbits = 6;
+            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            Tracev((stderr, "inflate:       codes ok\n"));
+            state->mode = LEN_;
+            if (flush == Z_TREES) goto inf_leave;
+        case LEN_:
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                if (state->mode == TYPE)
+                    state->back = -1;
+                break;
+            }
+            state->back = 0;
+            for (;;) {
+                here = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (here.op && (here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            state->length = (unsigned)here.val;
+            if ((int)(here.op) == 0) {
+                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+                        "inflate:         literal '%c'\n" :
+                        "inflate:         literal 0x%02x\n", here.val));
+                state->mode = LIT;
+                break;
+            }
+            if (here.op & 32) {
+                Tracevv((stderr, "inflate:         end of block\n"));
+                state->back = -1;
+                state->mode = TYPE;
+                break;
+            }
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+            Tracevv((stderr, "inflate:         length %u\n", state->length));
+            state->was = state->length;
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                here = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(here.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((here.op & 0xf0) == 0) {
+                last = here;
+                for (;;) {
+                    here = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + here.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+                state->back += last.bits;
+            }
+            DROPBITS(here.bits);
+            state->back += here.bits;
+            if (here.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)here.val;
+            state->extra = (unsigned)(here.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+                state->back += state->extra;
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->whave) {
+                    if (state->sane) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+                    Trace((stderr, "inflate.c too far\n"));
+                    copy -= state->whave;
+                    if (copy > state->length) copy = state->length;
+                    if (copy > left) copy = left;
+                    left -= copy;
+                    state->length -= copy;
+                    do {
+                        *put++ = 0;
+                    } while (--copy);
+                    if (state->length == 0) state->mode = LEN;
+                    break;
+#endif
+                }
+                if (copy > state->wnext) {
+                    copy -= state->wnext;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->wnext - copy);
+                if (copy > state->length) copy = state->length;
+            }
+            else {                              /* copy from output */
+                from = put - state->offset;
+                copy = state->length;
+            }
+            if (copy > left) copy = left;
+            left -= copy;
+            state->length -= copy;
+            do {
+                *put++ = *from++;
+            } while (--copy);
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if (out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((
+#ifdef GUNZIP
+                     state->flags ? hold :
+#endif
+                     REVERSE(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   check matches trailer\n"));
+            }
+#ifdef GUNZIP
+            state->mode = LENGTH;
+        case LENGTH:
+            if (state->wrap && state->flags) {
+                NEEDBITS(32);
+                if (hold != (state->total & 0xffffffffUL)) {
+                    strm->msg = (char *)"incorrect length check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+                Tracev((stderr, "inflate:   length matches trailer\n"));
+            }
+#endif
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call updatewindow() to create and/or update the window state.
+       Note: a memory error from inflate() is non-recoverable.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+        if (updatewindow(strm, out)) {
+            state->mode = MEM;
+            return Z_MEM_ERROR;
+        }
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if (state->wrap && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+    strm->data_type = state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0) +
+                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+    return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->window != Z_NULL) ZFREE(strm, state->window);
+    ZFREE(strm, strm->state);
+    strm->state = Z_NULL;
+    Tracev((stderr, "inflate: end\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+    struct inflate_state FAR *state;
+    unsigned long id;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary id */
+    if (state->mode == DICT) {
+        id = adler32(0L, Z_NULL, 0);
+        id = adler32(id, dictionary, dictLength);
+        if (id != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window */
+    if (updatewindow(strm, strm->avail_out)) {
+        state->mode = MEM;
+        return Z_MEM_ERROR;
+    }
+    if (dictLength > state->wsize) {
+        zmemcpy(state->window, dictionary + dictLength - state->wsize,
+                state->wsize);
+        state->whave = state->wsize;
+    }
+    else {
+        zmemcpy(state->window + state->wsize - dictLength, dictionary,
+                dictLength);
+        state->whave = dictLength;
+    }
+    state->havedict = 1;
+    Tracev((stderr, "inflate:   dictionary set\n"));
+    return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+    /* save header structure */
+    state->head = head;
+    head->done = 0;
+    return Z_OK;
+}
+
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+    unsigned got;
+    unsigned next;
+
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state FAR *state;
+
+    /* check parameters */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+    struct inflate_state FAR *state;
+    struct inflate_state FAR *copy;
+    unsigned char FAR *window;
+    unsigned wsize;
+
+    /* check input */
+    if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+        source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+        return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)source->state;
+
+    /* allocate space */
+    copy = (struct inflate_state FAR *)
+           ZALLOC(source, 1, sizeof(struct inflate_state));
+    if (copy == Z_NULL) return Z_MEM_ERROR;
+    window = Z_NULL;
+    if (state->window != Z_NULL) {
+        window = (unsigned char FAR *)
+                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        if (window == Z_NULL) {
+            ZFREE(source, copy);
+            return Z_MEM_ERROR;
+        }
+    }
+
+    /* copy state */
+    zmemcpy(dest, source, sizeof(z_stream));
+    zmemcpy(copy, state, sizeof(struct inflate_state));
+    if (state->lencode >= state->codes &&
+        state->lencode <= state->codes + ENOUGH - 1) {
+        copy->lencode = copy->codes + (state->lencode - state->codes);
+        copy->distcode = copy->codes + (state->distcode - state->codes);
+    }
+    copy->next = copy->codes + (state->next - state->codes);
+    if (window != Z_NULL) {
+        wsize = 1U << state->wbits;
+        zmemcpy(window, state->window, wsize);
+    }
+    copy->window = window;
+    dest->state = (struct internal_state FAR *)copy;
+    return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(strm, subvert)
+z_streamp strm;
+int subvert;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->sane = !subvert;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+    return Z_OK;
+#else
+    state->sane = 1;
+    return Z_DATA_ERROR;
+#endif
+}
+
+long ZEXPORT inflateMark(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
+    state = (struct inflate_state FAR *)strm->state;
+    return ((long)(state->back) << 16) +
+        (state->mode == COPY ? state->length :
+            (state->mode == MATCH ? state->was - state->length : 0));
+}
diff --git a/libgit2/deps/zlib/inflate.h b/libgit2/deps/zlib/inflate.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/inflate.h
@@ -0,0 +1,122 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2009 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in
+   the crc code when it is not needed.  For shared libraries, gzip decoding
+   should be left enabled. */
+#ifndef NO_GZIP
+#  define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD,       /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY_,      /* i/o: same as COPY below, but only first time in */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN_,       /* i: same as LEN below, but only first time in */
+            LEN,        /* i: waiting for length/lit/eob code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib) or (raw)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+                  HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+        (raw) -> TYPEDO
+    Read deflate blocks:
+            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+            STORED -> COPY_ -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN_
+            LEN_ -> LEN
+    Read deflate codes in fixed or dynamic block:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls.  Approximately 10K bytes. */
+struct inflate_state {
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+    gz_headerp head;            /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned wnext;             /* window write index */
+    unsigned char FAR *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const FAR *lencode;    /* starting table for length/literal codes */
+    code const FAR *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code FAR *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+    int sane;                   /* if false, allow invalid distance too far */
+    int back;                   /* bits back of last unprocessed length/lit */
+    unsigned was;               /* initial length of match */
+};
diff --git a/libgit2/deps/zlib/inftrees.c b/libgit2/deps/zlib/inftrees.c
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/inftrees.c
@@ -0,0 +1,330 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+   " inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/*
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code here;                  /* table entry for duplication */
+    code FAR *next;             /* next available space in table */
+    const unsigned short FAR *base;     /* base value table to use */
+    const unsigned short FAR *extra;    /* extra bits table to use */
+    int end;                    /* use base and extra for symbol > end */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
+    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577, 0, 0};
+    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+        28, 28, 29, 29, 64, 64};
+
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
+
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
+
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
+
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
+
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
+
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) {                     /* no symbols to code at all */
+        here.op = (unsigned char)64;    /* invalid code marker */
+        here.bits = (unsigned char)1;
+        here.val = (unsigned short)0;
+        *(*table)++ = here;             /* make a table to force an error */
+        *(*table)++ = here;
+        *bits = 1;
+        return 0;     /* no symbols, but wait for decoding to report error */
+    }
+    for (min = 1; min < max; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
+
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
+
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
+
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
+
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
+
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
+
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked for LENS and DIST tables against
+       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+       the initial root table size constants.  See the comments in inftrees.h
+       for more information.
+
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
+
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        end = 19;
+        break;
+    case LENS:
+        base = lbase;
+        base -= 257;
+        extra = lext;
+        extra -= 257;
+        end = 256;
+        break;
+    default:            /* DISTS */
+        base = dbase;
+        extra = dext;
+        end = -1;
+    }
+
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
+
+    /* check available table space */
+    if ((type == LENS && used >= ENOUGH_LENS) ||
+        (type == DISTS && used >= ENOUGH_DISTS))
+        return 1;
+
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        here.bits = (unsigned char)(len - drop);
+        if ((int)(work[sym]) < end) {
+            here.op = (unsigned char)0;
+            here.val = work[sym];
+        }
+        else if ((int)(work[sym]) > end) {
+            here.op = (unsigned char)(extra[work[sym]]);
+            here.val = base[work[sym]];
+        }
+        else {
+            here.op = (unsigned char)(32 + 64);         /* end of block */
+            here.val = 0;
+        }
+
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = here;
+        } while (fill != 0);
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
+
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
+
+            /* increment past last table */
+            next += min;            /* here min is 1 << curr */
+
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if ((type == LENS && used >= ENOUGH_LENS) ||
+                (type == DISTS && used >= ENOUGH_DISTS))
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
+    }
+
+    /*
+       Fill in rest of table for incomplete codes.  This loop is similar to the
+       loop above in incrementing huff for table indices.  It is assumed that
+       len is equal to curr + drop, so there is no loop needed to increment
+       through high index bits.  When the current sub-table is filled, the loop
+       drops back to the root table to fill in any remaining entries there.
+     */
+    here.op = (unsigned char)64;                /* invalid code marker */
+    here.bits = (unsigned char)(len - drop);
+    here.val = (unsigned short)0;
+    while (huff != 0) {
+        /* when done with sub-table, drop back to root table */
+        if (drop != 0 && (huff & mask) != low) {
+            drop = 0;
+            len = root;
+            next = *table;
+            here.bits = (unsigned char)len;
+        }
+
+        /* put invalid code marker in table */
+        next[huff >> drop] = here;
+
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
+    }
+
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
+}
diff --git a/libgit2/deps/zlib/inftrees.h b/libgit2/deps/zlib/inftrees.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/inftrees.h
@@ -0,0 +1,62 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    0001eeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table.  The maximum number of code structures is
+   1444, which is the sum of 852 for literal/length codes and 592 for distance
+   codes.  These values were found by exhaustive searches using the program
+   examples/enough.c found in the zlib distribtution.  The arguments to that
+   program are the number of symbols, the initial root table size, and the
+   maximum bit length of a code.  "enough 286 9 15" for literal/length codes
+   returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+   The initial root table size (9 or 6) is found in the fifth argument of the
+   inflate_table() calls in inflate.c and infback.c.  If the root table size is
+   changed, then these maximum sizes would be need to be recalculated and
+   updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
+                             unsigned codes, code FAR * FAR *table,
+                             unsigned FAR *bits, unsigned short FAR *work));
diff --git a/libgit2/deps/zlib/trees.c b/libgit2/deps/zlib/trees.c
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/trees.c
@@ -0,0 +1,1244 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2010 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ *  ALGORITHM
+ *
+ *      The "deflation" process uses several Huffman trees. The more
+ *      common source values are represented by shorter bit sequences.
+ *
+ *      Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values).  The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ *  REFERENCES
+ *
+ *      Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ *      Storer, James A.
+ *          Data Compression:  Methods and Theory, pp. 49-50.
+ *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.
+ *
+ *      Sedgewick, R.
+ *          Algorithms, p290.
+ *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+#  include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6      16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10    17
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+#define REPZ_11_138  18
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN  512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+#  include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+    const ct_data *static_tree;  /* static tree or NULL */
+    const intf *extra_bits;      /* extra bits for each code or NULL */
+    int     extra_base;          /* base index for extra_bits */
+    int     elems;               /* max number of elements in the tree */
+    int     max_length;          /* max bit length for the codes */
+};
+
+local static_tree_desc  static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc  static_d_desc =
+{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};
+
+local static_tree_desc  static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block     OF((deflate_state *s));
+local void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen     OF((deflate_state *s, tree_desc *desc));
+local void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree     OF((deflate_state *s, tree_desc *desc));
+local void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));
+local int  build_bl_tree  OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+                              int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+                              ct_data *dtree));
+local int  detect_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup      OF((deflate_state *s));
+local void bi_flush       OF((deflate_state *s));
+local void copy_block     OF((deflate_state *s, charf *buf, unsigned len,
+                              int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+   /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+#  define send_code(s, c, tree) \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+       send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+    put_byte(s, (uch)((w) & 0xff)); \
+    put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits      OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+    deflate_state *s;
+    int value;  /* value to send */
+    int length; /* number of bits */
+{
+    Tracevv((stderr," l %2d v %4x ", length, value));
+    Assert(length > 0 && length <= 15, "invalid length");
+    s->bits_sent += (ulg)length;
+
+    /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+     * unused bits in value.
+     */
+    if (s->bi_valid > (int)Buf_size - length) {
+        s->bi_buf |= (ush)value << s->bi_valid;
+        put_short(s, s->bi_buf);
+        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+        s->bi_valid += length - Buf_size;
+    } else {
+        s->bi_buf |= (ush)value << s->bi_valid;
+        s->bi_valid += length;
+    }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+  if (s->bi_valid > (int)Buf_size - len) {\
+    int val = value;\
+    s->bi_buf |= (ush)val << s->bi_valid;\
+    put_short(s, s->bi_buf);\
+    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+    s->bi_valid += len - Buf_size;\
+  } else {\
+    s->bi_buf |= (ush)(value) << s->bi_valid;\
+    s->bi_valid += len;\
+  }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+    static int static_init_done = 0;
+    int n;        /* iterates over tree elements */
+    int bits;     /* bit counter */
+    int length;   /* length value */
+    int code;     /* code value */
+    int dist;     /* distance index */
+    ush bl_count[MAX_BITS+1];
+    /* number of codes at each bit length for an optimal tree */
+
+    if (static_init_done) return;
+
+    /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+    static_l_desc.static_tree = static_ltree;
+    static_l_desc.extra_bits = extra_lbits;
+    static_d_desc.static_tree = static_dtree;
+    static_d_desc.extra_bits = extra_dbits;
+    static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+    /* Initialize the mapping length (0..255) -> length code (0..28) */
+    length = 0;
+    for (code = 0; code < LENGTH_CODES-1; code++) {
+        base_length[code] = length;
+        for (n = 0; n < (1<<extra_lbits[code]); n++) {
+            _length_code[length++] = (uch)code;
+        }
+    }
+    Assert (length == 256, "tr_static_init: length != 256");
+    /* Note that the length 255 (match length 258) can be represented
+     * in two different ways: code 284 + 5 bits or code 285, so we
+     * overwrite length_code[255] to use the best encoding:
+     */
+    _length_code[length-1] = (uch)code;
+
+    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+    dist = 0;
+    for (code = 0 ; code < 16; code++) {
+        base_dist[code] = dist;
+        for (n = 0; n < (1<<extra_dbits[code]); n++) {
+            _dist_code[dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: dist != 256");
+    dist >>= 7; /* from now on, all distances are divided by 128 */
+    for ( ; code < D_CODES; code++) {
+        base_dist[code] = dist << 7;
+        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+            _dist_code[256 + dist++] = (uch)code;
+        }
+    }
+    Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+    /* Construct the codes of the static literal tree */
+    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+    n = 0;
+    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+    /* Codes 286 and 287 do not exist, but we must include them in the
+     * tree construction to get a canonical Huffman tree (longest code
+     * all ones)
+     */
+    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+    /* The static distance tree is trivial: */
+    for (n = 0; n < D_CODES; n++) {
+        static_dtree[n].Len = 5;
+        static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+    }
+    static_init_done = 1;
+
+#  ifdef GEN_TREES_H
+    gen_trees_header();
+#  endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+#  ifndef DEBUG
+#    include <stdio.h>
+#  endif
+
+#  define SEPARATOR(i, last, width) \
+      ((i) == (last)? "\n};\n\n" :    \
+       ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+    FILE *header = fopen("trees.h", "w");
+    int i;
+
+    Assert (header != NULL, "Can't open trees.h");
+    fprintf(header,
+            "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+    fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+    for (i = 0; i < L_CODES+2; i++) {
+        fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+    }
+
+    fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+    }
+
+    fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+    for (i = 0; i < DIST_CODE_LEN; i++) {
+        fprintf(header, "%2u%s", _dist_code[i],
+                SEPARATOR(i, DIST_CODE_LEN-1, 20));
+    }
+
+    fprintf(header,
+        "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+        fprintf(header, "%2u%s", _length_code[i],
+                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+    }
+
+    fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+    for (i = 0; i < LENGTH_CODES; i++) {
+        fprintf(header, "%1u%s", base_length[i],
+                SEPARATOR(i, LENGTH_CODES-1, 20));
+    }
+
+    fprintf(header, "local const int base_dist[D_CODES] = {\n");
+    for (i = 0; i < D_CODES; i++) {
+        fprintf(header, "%5u%s", base_dist[i],
+                SEPARATOR(i, D_CODES-1, 10));
+    }
+
+    fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(s)
+    deflate_state *s;
+{
+    tr_static_init();
+
+    s->l_desc.dyn_tree = s->dyn_ltree;
+    s->l_desc.stat_desc = &static_l_desc;
+
+    s->d_desc.dyn_tree = s->dyn_dtree;
+    s->d_desc.stat_desc = &static_d_desc;
+
+    s->bl_desc.dyn_tree = s->bl_tree;
+    s->bl_desc.stat_desc = &static_bl_desc;
+
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+    s->compressed_len = 0L;
+    s->bits_sent = 0L;
+#endif
+
+    /* Initialize the first block of the first file: */
+    init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+    deflate_state *s;
+{
+    int n; /* iterates over tree elements */
+
+    /* Initialize the trees. */
+    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;
+    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;
+    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+    s->dyn_ltree[END_BLOCK].Freq = 1;
+    s->opt_len = s->static_len = 0L;
+    s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+    top = s->heap[SMALLEST]; \
+    s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+    pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+   (tree[n].Freq < tree[m].Freq || \
+   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+    deflate_state *s;
+    ct_data *tree;  /* the tree to restore */
+    int k;               /* node to move down */
+{
+    int v = s->heap[k];
+    int j = k << 1;  /* left son of k */
+    while (j <= s->heap_len) {
+        /* Set j to the smallest of the two sons: */
+        if (j < s->heap_len &&
+            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+            j++;
+        }
+        /* Exit if v is smaller than both sons */
+        if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+        /* Exchange v with the smallest son */
+        s->heap[k] = s->heap[j];  k = j;
+
+        /* And continue down the tree, setting j to the left son of k */
+        j <<= 1;
+    }
+    s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+local void gen_bitlen(s, desc)
+    deflate_state *s;
+    tree_desc *desc;    /* the tree descriptor */
+{
+    ct_data *tree        = desc->dyn_tree;
+    int max_code         = desc->max_code;
+    const ct_data *stree = desc->stat_desc->static_tree;
+    const intf *extra    = desc->stat_desc->extra_bits;
+    int base             = desc->stat_desc->extra_base;
+    int max_length       = desc->stat_desc->max_length;
+    int h;              /* heap index */
+    int n, m;           /* iterate over the tree elements */
+    int bits;           /* bit length */
+    int xbits;          /* extra bits */
+    ush f;              /* frequency */
+    int overflow = 0;   /* number of elements with bit length too large */
+
+    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+    /* In a first pass, compute the optimal bit lengths (which may
+     * overflow in the case of the bit length tree).
+     */
+    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+        n = s->heap[h];
+        bits = tree[tree[n].Dad].Len + 1;
+        if (bits > max_length) bits = max_length, overflow++;
+        tree[n].Len = (ush)bits;
+        /* We overwrite tree[n].Dad which is no longer needed */
+
+        if (n > max_code) continue; /* not a leaf node */
+
+        s->bl_count[bits]++;
+        xbits = 0;
+        if (n >= base) xbits = extra[n-base];
+        f = tree[n].Freq;
+        s->opt_len += (ulg)f * (bits + xbits);
+        if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+    }
+    if (overflow == 0) return;
+
+    Trace((stderr,"\nbit length overflow\n"));
+    /* This happens for example on obj2 and pic of the Calgary corpus */
+
+    /* Find the first bit length which could increase: */
+    do {
+        bits = max_length-1;
+        while (s->bl_count[bits] == 0) bits--;
+        s->bl_count[bits]--;      /* move one leaf down the tree */
+        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+        s->bl_count[max_length]--;
+        /* The brother of the overflow item also moves one step up,
+         * but this does not affect bl_count[max_length]
+         */
+        overflow -= 2;
+    } while (overflow > 0);
+
+    /* Now recompute all bit lengths, scanning in increasing frequency.
+     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+     * lengths instead of fixing only the wrong ones. This idea is taken
+     * from 'ar' written by Haruhiko Okumura.)
+     */
+    for (bits = max_length; bits != 0; bits--) {
+        n = s->bl_count[bits];
+        while (n != 0) {
+            m = s->heap[--h];
+            if (m > max_code) continue;
+            if ((unsigned) tree[m].Len != (unsigned) bits) {
+                Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+                s->opt_len += ((long)bits - (long)tree[m].Len)
+                              *(long)tree[m].Freq;
+                tree[m].Len = (ush)bits;
+            }
+            n--;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+    ct_data *tree;             /* the tree to decorate */
+    int max_code;              /* largest code with non zero frequency */
+    ushf *bl_count;            /* number of codes at each bit length */
+{
+    ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+    ush code = 0;              /* running code value */
+    int bits;                  /* bit index */
+    int n;                     /* code index */
+
+    /* The distribution counts are first used to generate the code values
+     * without bit reversal.
+     */
+    for (bits = 1; bits <= MAX_BITS; bits++) {
+        next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+    }
+    /* Check that the bit counts in bl_count are consistent. The last code
+     * must be all ones.
+     */
+    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            "inconsistent bit counts");
+    Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+    for (n = 0;  n <= max_code; n++) {
+        int len = tree[n].Len;
+        if (len == 0) continue;
+        /* Now reverse the bits */
+        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
+
+        Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+    }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+    deflate_state *s;
+    tree_desc *desc; /* the tree descriptor */
+{
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            s->heap[++(s->heap_len)] = max_code = n;
+            s->depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        s->depth[node] = 0;
+        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, tree, n);  /* n = node of least frequency */
+        m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        s->heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+                                s->depth[n] : s->depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        s->heap[SMALLEST] = node++;
+        pqdownheap(s, tree, SMALLEST);
+
+    } while (s->heap_len >= 2);
+
+    s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree;   /* the tree to be scanned */
+    int max_code;    /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    if (nextlen == 0) max_count = 138, min_count = 3;
+    tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            s->bl_tree[curlen].Freq += (ush)count;
+        } else if (curlen != 0) {
+            if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+            s->bl_tree[REP_3_6].Freq++;
+        } else if (count <= 10) {
+            s->bl_tree[REPZ_3_10].Freq++;
+        } else {
+            s->bl_tree[REPZ_11_138].Freq++;
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+    deflate_state *s;
+    ct_data *tree; /* the tree to be scanned */
+    int max_code;       /* and its largest code of non zero frequency */
+{
+    int n;                     /* iterates over all tree elements */
+    int prevlen = -1;          /* last emitted length */
+    int curlen;                /* length of current code */
+    int nextlen = tree[0].Len; /* length of next code */
+    int count = 0;             /* repeat count of the current code */
+    int max_count = 7;         /* max repeat count */
+    int min_count = 4;         /* min repeat count */
+
+    /* tree[max_code+1].Len = -1; */  /* guard already set */
+    if (nextlen == 0) max_count = 138, min_count = 3;
+
+    for (n = 0; n <= max_code; n++) {
+        curlen = nextlen; nextlen = tree[n+1].Len;
+        if (++count < max_count && curlen == nextlen) {
+            continue;
+        } else if (count < min_count) {
+            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+        } else if (curlen != 0) {
+            if (curlen != prevlen) {
+                send_code(s, curlen, s->bl_tree); count--;
+            }
+            Assert(count >= 3 && count <= 6, " 3_6?");
+            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+        } else if (count <= 10) {
+            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+        } else {
+            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+        }
+        count = 0; prevlen = curlen;
+        if (nextlen == 0) {
+            max_count = 138, min_count = 3;
+        } else if (curlen == nextlen) {
+            max_count = 6, min_count = 3;
+        } else {
+            max_count = 7, min_count = 4;
+        }
+    }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+    deflate_state *s;
+{
+    int max_blindex;  /* index of last bit length code of non zero freq */
+
+    /* Determine the bit length frequencies for literal and distance trees */
+    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+    /* Build the bit length tree: */
+    build_tree(s, (tree_desc *)(&(s->bl_desc)));
+    /* opt_len now includes the length of the tree representations, except
+     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+     */
+
+    /* Determine the number of bit length codes to send. The pkzip format
+     * requires that at least 4 bit length codes be sent. (appnote.txt says
+     * 3 but the actual value used is 4.)
+     */
+    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+    }
+    /* Update opt_len to include the bit length tree and counts */
+    s->opt_len += 3*(max_blindex+1) + 5+5+4;
+    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+            s->opt_len, s->static_len));
+
+    return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+    deflate_state *s;
+    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+    int rank;                    /* index in bl_order */
+
+    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+            "too many codes");
+    Tracev((stderr, "\nbl counts: "));
+    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+    send_bits(s, dcodes-1,   5);
+    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
+    for (rank = 0; rank < blcodes; rank++) {
+        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+    }
+    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
+    deflate_state *s;
+    charf *buf;       /* input block */
+    ulg stored_len;   /* length of input block */
+    int last;         /* one if this is the last block for a file */
+{
+    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */
+#ifdef DEBUG
+    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+    s->compressed_len += (stored_len + 4) << 3;
+#endif
+    copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void ZLIB_INTERNAL _tr_align(s)
+    deflate_state *s;
+{
+    send_bits(s, STATIC_TREES<<1, 3);
+    send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+    bi_flush(s);
+    /* Of the 10 bits for the empty block, we have already sent
+     * (10 - bi_valid) bits. The lookahead for the last real code (before
+     * the EOB of the previous block) was thus at least one plus the length
+     * of the EOB plus what we have just sent of the empty static block.
+     */
+    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+        send_bits(s, STATIC_TREES<<1, 3);
+        send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+        s->compressed_len += 10L;
+#endif
+        bi_flush(s);
+    }
+    s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
+    deflate_state *s;
+    charf *buf;       /* input block, or NULL if too old */
+    ulg stored_len;   /* length of input block */
+    int last;         /* one if this is the last block for a file */
+{
+    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+    int max_blindex = 0;  /* index of last bit length code of non zero freq */
+
+    /* Build the Huffman trees unless a stored block is forced */
+    if (s->level > 0) {
+
+        /* Check if the file is binary or text */
+        if (s->strm->data_type == Z_UNKNOWN)
+            s->strm->data_type = detect_data_type(s);
+
+        /* Construct the literal and distance trees */
+        build_tree(s, (tree_desc *)(&(s->l_desc)));
+        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+
+        build_tree(s, (tree_desc *)(&(s->d_desc)));
+        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+                s->static_len));
+        /* At this point, opt_len and static_len are the total bit lengths of
+         * the compressed block data, excluding the tree representations.
+         */
+
+        /* Build the bit length tree for the above two trees, and get the index
+         * in bl_order of the last bit length code to send.
+         */
+        max_blindex = build_bl_tree(s);
+
+        /* Determine the best encoding. Compute the block lengths in bytes. */
+        opt_lenb = (s->opt_len+3+7)>>3;
+        static_lenb = (s->static_len+3+7)>>3;
+
+        Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+                s->last_lit));
+
+        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+    } else {
+        Assert(buf != (char*)0, "lost buf");
+        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+    }
+
+#ifdef FORCE_STORED
+    if (buf != (char*)0) { /* force stored block */
+#else
+    if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+                       /* 4: two words for the lengths */
+#endif
+        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+         * Otherwise we can't have processed more than WSIZE input bytes since
+         * the last block flush, because compression would have been
+         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+         * transform a block into a stored block.
+         */
+        _tr_stored_block(s, buf, stored_len, last);
+
+#ifdef FORCE_STATIC
+    } else if (static_lenb >= 0) { /* force static trees */
+#else
+    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+        send_bits(s, (STATIC_TREES<<1)+last, 3);
+        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->static_len;
+#endif
+    } else {
+        send_bits(s, (DYN_TREES<<1)+last, 3);
+        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+                       max_blindex+1);
+        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+        s->compressed_len += 3 + s->opt_len;
+#endif
+    }
+    Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+    /* The above check is made mod 2^32, for files larger than 512 MB
+     * and uLong implemented on 32 bits.
+     */
+    init_block(s);
+
+    if (last) {
+        bi_windup(s);
+#ifdef DEBUG
+        s->compressed_len += 7;  /* align on byte boundary */
+#endif
+    }
+    Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+           s->compressed_len-7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally (s, dist, lc)
+    deflate_state *s;
+    unsigned dist;  /* distance of matched string */
+    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+    s->d_buf[s->last_lit] = (ush)dist;
+    s->l_buf[s->last_lit++] = (uch)lc;
+    if (dist == 0) {
+        /* lc is the unmatched char */
+        s->dyn_ltree[lc].Freq++;
+    } else {
+        s->matches++;
+        /* Here, lc is the match length - MIN_MATCH */
+        dist--;             /* dist = match distance - 1 */
+        Assert((ush)dist < (ush)MAX_DIST(s) &&
+               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+               (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+        s->dyn_dtree[d_code(dist)].Freq++;
+    }
+
+#ifdef TRUNCATE_BLOCK
+    /* Try to guess if it is profitable to stop the current block here */
+    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+        /* Compute an upper bound for the compressed length */
+        ulg out_length = (ulg)s->last_lit*8L;
+        ulg in_length = (ulg)((long)s->strstart - s->block_start);
+        int dcode;
+        for (dcode = 0; dcode < D_CODES; dcode++) {
+            out_length += (ulg)s->dyn_dtree[dcode].Freq *
+                (5L+extra_dbits[dcode]);
+        }
+        out_length >>= 3;
+        Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+               s->last_lit, in_length, out_length,
+               100L - out_length*100L/in_length));
+        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+    }
+#endif
+    return (s->last_lit == s->lit_bufsize-1);
+    /* We avoid equality with lit_bufsize because of wraparound at 64K
+     * on 16 bit machines and because stored blocks are restricted to
+     * 64K-1 bytes.
+     */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+    deflate_state *s;
+    ct_data *ltree; /* literal tree */
+    ct_data *dtree; /* distance tree */
+{
+    unsigned dist;      /* distance of matched string */
+    int lc;             /* match length or unmatched char (if dist == 0) */
+    unsigned lx = 0;    /* running index in l_buf */
+    unsigned code;      /* the code to send */
+    int extra;          /* number of extra bits to send */
+
+    if (s->last_lit != 0) do {
+        dist = s->d_buf[lx];
+        lc = s->l_buf[lx++];
+        if (dist == 0) {
+            send_code(s, lc, ltree); /* send a literal byte */
+            Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+        } else {
+            /* Here, lc is the match length - MIN_MATCH */
+            code = _length_code[lc];
+            send_code(s, code+LITERALS+1, ltree); /* send the length code */
+            extra = extra_lbits[code];
+            if (extra != 0) {
+                lc -= base_length[code];
+                send_bits(s, lc, extra);       /* send the extra length bits */
+            }
+            dist--; /* dist is now the match distance - 1 */
+            code = d_code(dist);
+            Assert (code < D_CODES, "bad d_code");
+
+            send_code(s, code, dtree);       /* send the distance code */
+            extra = extra_dbits[code];
+            if (extra != 0) {
+                dist -= base_dist[code];
+                send_bits(s, dist, extra);   /* send the extra distance bits */
+            }
+        } /* literal or match pair ? */
+
+        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+               "pendingBuf overflow");
+
+    } while (lx < s->last_lit);
+
+    send_code(s, END_BLOCK, ltree);
+    s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ *    a) There are no non-portable control characters belonging to the
+ *       "black list" (0..6, 14..25, 28..31).
+ *    b) There is at least one printable character belonging to the
+ *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ *   "gray list" that is ignored in this detection algorithm:
+ *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(s)
+    deflate_state *s;
+{
+    /* black_mask is the bit mask of black-listed bytes
+     * set bits 0..6, 14..25, and 28..31
+     * 0xf3ffc07f = binary 11110011111111111100000001111111
+     */
+    unsigned long black_mask = 0xf3ffc07fUL;
+    int n;
+
+    /* Check for non-textual ("black-listed") bytes. */
+    for (n = 0; n <= 31; n++, black_mask >>= 1)
+        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+            return Z_BINARY;
+
+    /* Check for textual ("white-listed") bytes. */
+    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+            || s->dyn_ltree[13].Freq != 0)
+        return Z_TEXT;
+    for (n = 32; n < LITERALS; n++)
+        if (s->dyn_ltree[n].Freq != 0)
+            return Z_TEXT;
+
+    /* There are no "black-listed" or "white-listed" bytes:
+     * this stream either is empty or has tolerated ("gray-listed") bytes only.
+     */
+    return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+    unsigned code; /* the value to invert */
+    int len;       /* its bit length */
+{
+    register unsigned res = 0;
+    do {
+        res |= code & 1;
+        code >>= 1, res <<= 1;
+    } while (--len > 0);
+    return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+    deflate_state *s;
+{
+    if (s->bi_valid == 16) {
+        put_short(s, s->bi_buf);
+        s->bi_buf = 0;
+        s->bi_valid = 0;
+    } else if (s->bi_valid >= 8) {
+        put_byte(s, (Byte)s->bi_buf);
+        s->bi_buf >>= 8;
+        s->bi_valid -= 8;
+    }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+    deflate_state *s;
+{
+    if (s->bi_valid > 8) {
+        put_short(s, s->bi_buf);
+    } else if (s->bi_valid > 0) {
+        put_byte(s, (Byte)s->bi_buf);
+    }
+    s->bi_buf = 0;
+    s->bi_valid = 0;
+#ifdef DEBUG
+    s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+    deflate_state *s;
+    charf    *buf;    /* the input data */
+    unsigned len;     /* its length */
+    int      header;  /* true if block header must be written */
+{
+    bi_windup(s);        /* align on byte boundary */
+    s->last_eob_len = 8; /* enough lookahead for inflate */
+
+    if (header) {
+        put_short(s, (ush)len);
+        put_short(s, (ush)~len);
+#ifdef DEBUG
+        s->bits_sent += 2*16;
+#endif
+    }
+#ifdef DEBUG
+    s->bits_sent += (ulg)len<<3;
+#endif
+    while (len--) {
+        put_byte(s, *buf++);
+    }
+}
diff --git a/libgit2/deps/zlib/trees.h b/libgit2/deps/zlib/trees.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},
+{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},
+{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},
+{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},
+{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},
+{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},
+{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},
+{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},
+{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},
+{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},
+{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},
+{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},
+{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},
+{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},
+{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},
+{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},
+{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},
+{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},
+{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},
+{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},
+{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},
+{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},
+{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},
+{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},
+{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},
+{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},
+{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},
+{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},
+{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},
+{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},
+{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},
+{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},
+{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},
+{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},
+{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},
+{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},
+{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},
+{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},
+{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},
+{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},
+{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},
+{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},
+{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},
+{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},
+{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},
+{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},
+{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},
+{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},
+{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},
+{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},
+{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},
+{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},
+{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},
+{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},
+{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},
+{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},
+{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},
+{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+ 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,
+   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,
+ 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+};
+
diff --git a/libgit2/deps/zlib/zconf.h b/libgit2/deps/zlib/zconf.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/zconf.h
@@ -0,0 +1,57 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+#include "../../src/common.h"
+
+#define NO_GZIP
+#define STDC
+
+/* Jeez, don't complain about non-prototype
+ * forms, we didn't write zlib */
+#if defined(_MSC_VER)
+#	pragma warning( disable : 4131 )
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#define MAX_MEM_LEVEL 9
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#define MAX_WBITS   15 /* 32K LZ77 window */
+
+#define ZEXTERN extern
+#define ZEXPORT
+#define ZEXPORTVA
+#ifndef FAR
+#	define FAR
+#endif
+#define OF(args)  args
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+typedef Byte  FAR Bytef;
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+typedef void const *voidpc;
+typedef void FAR   *voidpf;
+typedef void       *voidp;
+
+#define z_off_t git_off_t
+#define z_off64_t z_off_t
+
+#endif /* ZCONF_H */
diff --git a/libgit2/deps/zlib/zlib.h b/libgit2/deps/zlib/zlib.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/zlib.h
@@ -0,0 +1,1613 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.5, April 19th, 2010
+
+  Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.5"
+#define ZLIB_VERNUM 0x1250
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 5
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+    The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+    The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+    This library can optionally read and write gzip streams in memory as well.
+
+    The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
+   opaque value.
+
+     zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use in the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+#define Z_TREES         6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows.  deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).  Some
+    output may be provided even if flush is not set.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumulate before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed code
+  block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error.  After
+  deflate has returned Z_STREAM_END, the only possible operations on the stream
+  are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step.  In this case, avail_out must be at least the
+  value returned by deflateBound (see below).  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
+  binary.  This field is only for information purposes and does not affect the
+  compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression.  The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
+   exact value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit() does not process any header information -- that is deferred
+   until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows.  inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing will
+    resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all the uncompressed data.  (The size
+  of the uncompressed data may have been saved by the compressor for this
+  purpose.) The next operation on this stream must be inflateEnd to deallocate
+  the decompression state.  The use of Z_FINISH is never required, but can be
+  used to inform inflate that a faster approach may be used for the single
+  inflate() call.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call.  So the only effect of the flush parameter in this implementation
+  is on the return value of inflate(), as noted below, or when it returns early
+  because Z_BLOCK or Z_TREES is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the adler32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below.  At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained, so applications that need that information should
+  instead use raw inflate, see inflateInit2() below, or inflateBack() and
+  perform their own processing of the gzip header and trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent.  In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
+
+     The method parameter is the compression method.  It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm.  Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output.  This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any call
+   of deflate.  The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary.  Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor.  (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort).  deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter.  The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.  The
+   stream will keep the same compression level and any other attributes that
+   may have been set by deflateInit2.
+
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression level is changed, the input available so far is
+   compressed with the old level (and may be flushed); the new level will take
+   effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to be
+   compressed and flushed.  In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+   strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+     If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter.  The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used.  If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream.  This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values.  If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is.  Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called
+   immediately after inflateInit2() or inflateReset() and before any call of
+   inflate() to set the dictionary.  The application must insure that the
+   dictionary that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value).  inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a full flush point (see above the
+   description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+   if no more input was provided, Z_DATA_ERROR if no flush point has been
+   found, or Z_STREAM_ERROR if the stream structure was inconsistent.  In the
+   success case, the application may save the current current value of total_in
+   which indicates where valid compressed data was found.  In the error case,
+   the application may repeatedly call inflateSync, providing more input each
+   time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.
+
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above or -1 << 16 if the provided
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
+
+     The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+     If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the normal
+   behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.) Note that inflateBack()
+   cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer.  The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer.  Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed buffer.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef voidp gzFile;       /* opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.) Also "a"
+   can be used instead of "w" to request that the gzip stream that will be
+   written be appended to the file.  "+" will result in an error, since reading
+   and writing to the same gzip file is not supported.
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Two buffers are allocated, either both of the specified size when
+   writing, or one of the specified size and the other twice that size when
+   reading.  A larger buffer size of, for example, 64K or 128K bytes will
+   noticeably increase the speed of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy.  See the description
+   of deflateInit2 for the meaning of these parameters.
+
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file was not in gzip format, gzread copies the given number of
+   bytes into the buffer.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream, or failing that, reading the rest
+   of the input file directly without decompression.  The entire input file
+   will be read if gzread is called until it returns less than the requested
+   len.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or 0 in case of error.  The number of
+   uncompressed bytes written is limited to 8191, or one less than the buffer
+   size given to gzbuffer().  The caller should assure that this limit is not
+   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
+   nothing written.  In this case, there may also be a buffer overflow with
+   unpredictable consequences, which is possible only if zlib was compiled with
+   the insecure functions sprintf() or vsprintf() because the secure snprintf()
+   or vsnprintf() functions were not available.  This can be determined using
+   zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+     Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+
+     gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatented gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow.  If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+     gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.  This state can change from
+   false to true while reading the input file if the end of a gzip stream is
+   reached, but is followed by data that is not another gzip stream.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the compression
+   library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster.
+
+   Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the for the crc.  Pre- and post-conditioning (one's
+   complement) is performed within this function so it shouldn't be done by the
+   application.
+
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+                                            ZLIB_VERSION, sizeof(z_stream))
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
+#  define gzopen gzopen64
+#  define gzseek gzseek64
+#  define gztell gztell64
+#  define gzoffset gzoffset64
+#  define adler32_combine adler32_combine64
+#  define crc32_combine crc32_combine64
+#  ifdef _LARGEFILE64_SOURCE
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+/* hack for buggy compilers */
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;};
+#endif
+
+/* undocumented functions */
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/libgit2/deps/zlib/zutil.c b/libgit2/deps/zlib/zutil.c
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/zutil.c
@@ -0,0 +1,318 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state      {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary",     /* Z_NEED_DICT       2  */
+"stream end",          /* Z_STREAM_END      1  */
+"",                    /* Z_OK              0  */
+"file error",          /* Z_ERRNO         (-1) */
+"stream error",        /* Z_STREAM_ERROR  (-2) */
+"data error",          /* Z_DATA_ERROR    (-3) */
+"insufficient memory", /* Z_MEM_ERROR     (-4) */
+"buffer error",        /* Z_BUF_ERROR     (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+    return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+    uLong flags;
+
+    flags = 0;
+    switch ((int)(sizeof(uInt))) {
+    case 2:     break;
+    case 4:     flags += 1;     break;
+    case 8:     flags += 2;     break;
+    default:    flags += 3;
+    }
+    switch ((int)(sizeof(uLong))) {
+    case 2:     break;
+    case 4:     flags += 1 << 2;        break;
+    case 8:     flags += 2 << 2;        break;
+    default:    flags += 3 << 2;
+    }
+    switch ((int)(sizeof(voidpf))) {
+    case 2:     break;
+    case 4:     flags += 1 << 4;        break;
+    case 8:     flags += 2 << 4;        break;
+    default:    flags += 3 << 4;
+    }
+    switch ((int)(sizeof(z_off_t))) {
+    case 2:     break;
+    case 4:     flags += 1 << 6;        break;
+    case 8:     flags += 2 << 6;        break;
+    default:    flags += 3 << 6;
+    }
+#ifdef DEBUG
+    flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+    flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+    flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+    flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+    flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+    flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+    flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+    flags += 1L << 20;
+#endif
+#ifdef FASTEST
+    flags += 1L << 21;
+#endif
+#ifdef STDC
+#  ifdef NO_vsnprintf
+        flags += 1L << 25;
+#    ifdef HAS_vsprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_vsnprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#else
+        flags += 1L << 24;
+#  ifdef NO_snprintf
+        flags += 1L << 25;
+#    ifdef HAS_sprintf_void
+        flags += 1L << 26;
+#    endif
+#  else
+#    ifdef HAS_snprintf_void
+        flags += 1L << 26;
+#    endif
+#  endif
+#endif
+    return flags;
+}
+
+#ifdef DEBUG
+
+#  ifndef verbose
+#    define verbose 0
+#  endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error (m)
+    char *m;
+{
+    fprintf(stderr, "%s\n", m);
+    exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+    int err;
+{
+    return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+    /* The Microsoft C Run-Time Library for Windows CE doesn't have
+     * errno.  We define it as a global variable to simplify porting.
+     * Its value is always 0 and should not be used.
+     */
+    int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(dest, source, len)
+    Bytef* dest;
+    const Bytef* source;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = *source++; /* ??? to be unrolled */
+    } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(s1, s2, len)
+    const Bytef* s1;
+    const Bytef* s2;
+    uInt  len;
+{
+    uInt j;
+
+    for (j = 0; j < len; j++) {
+        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+    }
+    return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(dest, len)
+    Bytef* dest;
+    uInt  len;
+{
+    if (len == 0) return;
+    do {
+        *dest++ = 0;  /* ??? to be unrolled */
+    } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+    voidpf org_ptr;
+    voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+    voidpf buf = opaque; /* just to make some compilers happy */
+    ulg bsize = (ulg)items*size;
+
+    /* If we allocate less than 65520 bytes, we assume that farmalloc
+     * will return a usable pointer which doesn't have to be normalized.
+     */
+    if (bsize < 65520L) {
+        buf = farmalloc(bsize);
+        if (*(ush*)&buf != 0) return buf;
+    } else {
+        buf = farmalloc(bsize + 16L);
+    }
+    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+    table[next_ptr].org_ptr = buf;
+
+    /* Normalize the pointer to seg:0 */
+    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+    *(ush*)&buf = 0;
+    table[next_ptr++].new_ptr = buf;
+    return buf;
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    int n;
+    if (*(ush*)&ptr != 0) { /* object < 64K */
+        farfree(ptr);
+        return;
+    }
+    /* Find the original pointer */
+    for (n = 0; n < next_ptr; n++) {
+        if (ptr != table[n].new_ptr) continue;
+
+        farfree(table[n].org_ptr);
+        while (++n < next_ptr) {
+            table[n-1] = table[n];
+        }
+        next_ptr--;
+        return;
+    }
+    ptr = opaque; /* just to make some compilers happy */
+    Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+#  define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+#  define _halloc  halloc
+#  define _hfree   hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+{
+    if (opaque) opaque = 0; /* to make compiler happy */
+    _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp  malloc OF((uInt size));
+extern voidp  calloc OF((uInt items, uInt size));
+extern void   free   OF((voidpf ptr));
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
+    voidpf opaque;
+    unsigned items;
+    unsigned size;
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+                              (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree (opaque, ptr)
+    voidpf opaque;
+    voidpf ptr;
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/libgit2/deps/zlib/zutil.h b/libgit2/deps/zlib/zutil.h
new file mode 100644
--- /dev/null
+++ b/libgit2/deps/zlib/zutil.h
@@ -0,0 +1,274 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2010 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
+#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+#  define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#ifdef STDC
+#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+#    include <stddef.h>
+#  endif
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+#  define OS_CODE  0x00
+#  if defined(__TURBOC__) || defined(__BORLANDC__)
+#    if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+       /* Allow compilation with ANSI keywords only enabled */
+       void _Cdecl farfree( void *block );
+       void *_Cdecl farmalloc( unsigned long nbytes );
+#    else
+#      include <alloc.h>
+#    endif
+#  else /* MSC or DJGPP */
+#    include <malloc.h>
+#  endif
+#endif
+
+#ifdef AMIGA
+#  define OS_CODE  0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+#  define OS_CODE  0x02
+#  define F_OPEN(name, mode) \
+     fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+#  define OS_CODE  0x05
+#endif
+
+#ifdef OS2
+#  define OS_CODE  0x06
+#  ifdef M_I86
+#    include <malloc.h>
+#  endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+#  define OS_CODE  0x07
+#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#    include <unix.h> /* for fdopen */
+#  else
+#    ifndef fdopen
+#      define fdopen(fd,mode) NULL /* No fdopen() */
+#    endif
+#  endif
+#endif
+
+#ifdef TOPS20
+#  define OS_CODE  0x0a
+#endif
+
+#ifdef WIN32
+#  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
+#    define OS_CODE  0x0b
+#  endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+#  define OS_CODE  0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+#  define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+#  if defined(_WIN32_WCE)
+#    define fdopen(fd,mode) NULL /* No fdopen() */
+#    ifndef _PTRDIFF_T_DEFINED
+       typedef int ptrdiff_t;
+#      define _PTRDIFF_T_DEFINED
+#    endif
+#  else
+#    define fdopen(fd,type)  _fdopen(fd,type)
+#  endif
+#endif
+
+#if defined(__BORLANDC__)
+  #pragma warn -8004
+  #pragma warn -8008
+  #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#endif
+
+        /* common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#if defined(__CYGWIN__)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+#ifndef HAVE_VSNPRINTF
+#  ifdef MSDOS
+     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+        but for now we just assume it doesn't. */
+#    define NO_vsnprintf
+#  endif
+#  ifdef __TURBOC__
+#    define NO_vsnprintf
+#  endif
+#  ifdef WIN32
+     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
+#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+#         define vsnprintf _vsnprintf
+#      endif
+#    endif
+#  endif
+#  ifdef __SASC
+#    define NO_vsnprintf
+#  endif
+#endif
+#ifdef VMS
+#  define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+#  define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+  * You may have to use the same strategy for Borland C (untested).
+  * The __SC__ check is for Symantec.
+  */
+#  define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+#  define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+#    define zmemcpy _fmemcpy
+#    define zmemcmp _fmemcmp
+#    define zmemzero(dest, len) _fmemset(dest, 0, len)
+#  else
+#    define zmemcpy memcpy
+#    define zmemcmp memcmp
+#    define zmemzero(dest, len) memset(dest, 0, len)
+#  endif
+#else
+   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  include <stdio.h>
+   extern int ZLIB_INTERNAL z_verbose;
+   extern void ZLIB_INTERNAL z_error OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+                        unsigned size));
+void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
diff --git a/libgit2/include/git2.h b/libgit2/include/git2.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2.h
@@ -0,0 +1,56 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDE_git_git_h__
+#define INCLUDE_git_git_h__
+
+#define LIBGIT2_VERSION "0.10.0"
+#define LIBGIT2_VER_MAJOR 0
+#define LIBGIT2_VER_MINOR 10
+#define LIBGIT2_VER_REVISION 0
+
+#include "git2/common.h"
+#include "git2/errors.h"
+#include "git2/zlib.h"
+
+#include "git2/types.h"
+
+#include "git2/oid.h"
+#include "git2/signature.h"
+#include "git2/odb.h"
+
+#include "git2/repository.h"
+#include "git2/revwalk.h"
+#include "git2/refs.h"
+
+#include "git2/object.h"
+#include "git2/blob.h"
+#include "git2/commit.h"
+#include "git2/tag.h"
+#include "git2/tree.h"
+
+#include "git2/index.h"
+
+#endif
diff --git a/libgit2/include/git2/blob.h b/libgit2/include/git2/blob.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/blob.h
@@ -0,0 +1,128 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_blob_h__
+#define INCLUDE_git_blob_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+#include "object.h"
+
+/**
+ * @file git2/blob.h
+ * @brief Git blob load and write routines
+ * @defgroup git_blob Git blob load and write routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Lookup a blob object from a repository.
+ * The generated blob object is owned by the revision
+ * repo and shall not be freed by the user.
+ *
+ * @param blob pointer to the looked up blob
+ * @param repo the repo to use when locating the blob.
+ * @param id identity of the blob to locate.
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_blob_lookup(git_blob **blob, git_repository *repo, const git_oid *id)
+{
+	return git_object_lookup((git_object **)blob, repo, id, GIT_OBJ_BLOB);
+}
+
+/**
+ * Create a new in-memory git_blob.
+ *
+ * The blob object must be manually filled using
+ * the 'set_rawcontent' methods before it can
+ * be written back to disk.
+ *
+ * @param blob pointer to the new blob
+ * @param repo The repository where the object will reside
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_blob_new(git_blob **blob, git_repository *repo)
+{
+	return git_object_new((git_object **)blob, repo, GIT_OBJ_BLOB);
+}
+
+/**
+ * Fill a blob with the contents inside
+ * the pointed file.
+ *
+ * @param blob pointer to the new blob
+ * @param filename name of the file to read
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_blob_set_rawcontent_fromfile(git_blob *blob, const char *filename);
+
+/**
+ * Fill a blob with the contents inside
+ * the pointed buffer
+ *
+ * @param blob pointer to the blob
+ * @param buffer buffer with the contents for the blob
+ * @param len size of the buffer
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_blob_set_rawcontent(git_blob *blob, const void *buffer, size_t len);
+
+/**
+ * Get a read-only buffer with the raw content of a blob.
+ *
+ * A pointer to the raw content of a blob is returned;
+ * this pointer is owned internally by the object and shall
+ * not be free'd. The pointer may be invalidated at a later
+ * time (e.g. when changing the contents of the blob).
+ *
+ * @param blob pointer to the blob
+ * @return the pointer; NULL if the blob has no contents
+ */
+GIT_EXTERN(const void *) git_blob_rawcontent(git_blob *blob);
+
+/**
+ * Get the size in bytes of the contents of a blob
+ *
+ * @param blob pointer to the blob
+ * @return size on bytes
+ */
+GIT_EXTERN(int) git_blob_rawsize(git_blob *blob);
+
+/**
+ * Read a file from the working folder of a repository
+ * and write it to the Object Database as a loose blob,
+ * if such doesn't exist yet.
+ *
+ * @param written_id return the id of the written blob
+ * @param repo repository where the blob will be written
+ * @param path file from which the blob will be created
+ */
+GIT_EXTERN(int) git_blob_writefile(git_oid *written_id, git_repository *repo, const char *path);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/commit.h b/libgit2/include/git2/commit.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/commit.h
@@ -0,0 +1,188 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_commit_h__
+#define INCLUDE_git_commit_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+#include "object.h"
+
+/**
+ * @file git2/commit.h
+ * @brief Git commit parsing, formatting routines
+ * @defgroup git_commit Git commit parsing, formatting routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Lookup a commit object from a repository.
+ * The generated commit object is owned by the revision
+ * repo and shall not be freed by the user.
+ *
+ * @param commit pointer to the looked up commit
+ * @param repo the repo to use when locating the commit.
+ * @param id identity of the commit to locate.  If the object is
+ *        an annotated tag it will be peeled back to the commit.
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_commit_lookup(git_commit **commit, git_repository *repo, const git_oid *id)
+{
+	return git_object_lookup((git_object **)commit, repo, id, GIT_OBJ_COMMIT);
+}
+
+/**
+ * Create a new in-memory git_commit.
+ *
+ * The commit object must be manually filled using
+ * setter methods before it can be written to its
+ * repository.
+ *
+ * @param commit pointer to the new commit
+ * @param repo The repository where the object will reside
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_commit_new(git_commit **commit, git_repository *repo)
+{
+	return git_object_new((git_object **)commit, repo, GIT_OBJ_COMMIT);
+}
+
+/**
+ * Get the id of a commit.
+ * @param commit a previously loaded commit.
+ * @return object identity for the commit.
+ */
+GIT_EXTERN(const git_oid *) git_commit_id(git_commit *commit);
+
+/**
+ * Get the short (one line) message of a commit.
+ * @param commit a previously loaded commit.
+ * @return the short message of a commit
+ */
+GIT_EXTERN(const char *) git_commit_message_short(git_commit *commit);
+
+/**
+ * Get the full message of a commit.
+ * @param commit a previously loaded commit.
+ * @return the message of a commit
+ */
+GIT_EXTERN(const char *) git_commit_message(git_commit *commit);
+
+/**
+ * Get the commit time (i.e. committer time) of a commit.
+ * @param commit a previously loaded commit.
+ * @return the time of a commit
+ */
+GIT_EXTERN(time_t) git_commit_time(git_commit *commit);
+
+/**
+ * Get the commit timezone offset (i.e. committer's preferred timezone) of a commit.
+ * @param commit a previously loaded commit.
+ * @return positive or negative timezone offset, in minutes from UTC
+ */
+GIT_EXTERN(int) git_commit_time_offset(git_commit *commit);
+
+/**
+ * Get the committer of a commit.
+ * @param commit a previously loaded commit.
+ * @return the committer of a commit
+ */
+GIT_EXTERN(const git_signature *) git_commit_committer(git_commit *commit);
+
+/**
+ * Get the author of a commit.
+ * @param commit a previously loaded commit.
+ * @return the author of a commit
+ */
+GIT_EXTERN(const git_signature *) git_commit_author(git_commit *commit);
+
+/**
+ * Get the tree pointed to by a commit.
+ * @param tree_out pointer where to store the tree object
+ * @param commit a previously loaded commit.
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_commit_tree(git_tree **tree_out, git_commit *commit);
+
+/**
+ * Get the number of parents of this commit
+ *
+ * @param commit a previously loaded commit.
+ * @return integer of count of parents
+ */
+GIT_EXTERN(unsigned int) git_commit_parentcount(git_commit *commit);
+
+/**
+ * Get the specified parent of the commit.
+ *
+ * @param parent Pointer where to store the parent commit
+ * @param commit a previously loaded commit.
+ * @param n the position of the parent (from 0 to `parentcount`)
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n);
+
+/**
+ * Add a new parent commit to an existing commit
+ * @param commit the commit object
+ * @param new_parent the new commit which will be a parent
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_commit_add_parent(git_commit *commit, git_commit *new_parent);
+
+/**
+ * Set the message of a commit
+ * @param commit the commit object
+ * @param message the new message
+ */
+GIT_EXTERN(void) git_commit_set_message(git_commit *commit, const char *message);
+
+/**
+ * Set the committer of a commit
+ * @param commit the commit object
+ * @param author_sig signature of the committer
+ */
+GIT_EXTERN(void) git_commit_set_committer(git_commit *commit, const git_signature *committer_sig);
+
+/**
+ * Set the author of a commit
+ * @param commit the commit object
+ * @param author_sig signature of the author
+ */
+GIT_EXTERN(void) git_commit_set_author(git_commit *commit, const git_signature *author_sig);
+
+/**
+ * Set the tree which is pointed to by a commit
+ * @param commit the commit object
+ * @param tree the new tree
+ * @param 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_commit_set_tree(git_commit *commit, git_tree *tree);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/common.h b/libgit2/include/git2/common.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/common.h
@@ -0,0 +1,172 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_common_h__
+#define INCLUDE_git_common_h__
+
+#include "thread-utils.h"
+#include <time.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+# define GIT_BEGIN_DECL  extern "C" {
+# define GIT_END_DECL    }
+#else
+  /** Start declarations in C mode */
+# define GIT_BEGIN_DECL  /* empty */
+  /** End declarations in C mode */
+# define GIT_END_DECL    /* empty */
+#endif
+
+/** Declare a public function exported for application use. */
+#ifdef __GNUC__
+# define GIT_EXTERN(type) extern \
+			  __attribute__((visibility("default"))) \
+			  type
+#elif defined(_MSC_VER)
+# define GIT_EXTERN(type) __declspec(dllexport) type
+#else
+# define GIT_EXTERN(type) extern type
+#endif
+
+/** Declare a public TLS symbol exported for application use. */
+#ifdef __GNUC__
+# define GIT_EXTERN_TLS(type) extern \
+			      __attribute__((visibility("default"))) \
+			      GIT_TLS \
+			      type
+#elif defined(_MSC_VER)
+# define GIT_EXTERN_TLS(type) __declspec(dllexport) GIT_TLS type
+#else
+# define GIT_EXTERN_TLS(type) extern GIT_TLS type
+#endif
+
+/** Declare a function as always inlined. */
+#if defined(_MSC_VER)
+# define GIT_INLINE(type) static __inline type
+#else
+# define GIT_INLINE(type) static inline type
+#endif
+
+/** Declare a function's takes printf style arguments. */
+#ifdef __GNUC__
+# define GIT_FORMAT_PRINTF(a,b) __attribute__((format (printf, a, b)))
+#else
+# define GIT_FORMAT_PRINTF(a,b) /* empty */
+#endif
+
+/**
+ * @file git2/common.h
+ * @brief Git common platform definitions
+ * @defgroup git_common Git common platform definitions
+ * @ingroup Git
+ * @{
+ */
+
+/** Operation completed successfully. */
+#define GIT_SUCCESS 0
+
+/**
+ * Operation failed, with unspecified reason.
+ * This value also serves as the base error code; all other
+ * error codes are subtracted from it such that all errors
+ * are < 0, in typical POSIX C tradition.
+ */
+#define GIT_ERROR -1
+
+/** Input was not a properly formatted Git object id. */
+#define GIT_ENOTOID (GIT_ERROR - 1)
+
+/** Input does not exist in the scope searched. */
+#define GIT_ENOTFOUND (GIT_ERROR - 2)
+
+/** Not enough space available. */
+#define GIT_ENOMEM (GIT_ERROR - 3)
+
+/** Consult the OS error information. */
+#define GIT_EOSERR (GIT_ERROR - 4)
+
+/** The specified object is of invalid type */
+#define GIT_EOBJTYPE (GIT_ERROR - 5)
+
+/** The specified object has its data corrupted */
+#define GIT_EOBJCORRUPTED (GIT_ERROR - 6)
+
+/** The specified repository is invalid */
+#define GIT_ENOTAREPO (GIT_ERROR - 7)
+
+/** The object type is invalid or doesn't match */
+#define GIT_EINVALIDTYPE (GIT_ERROR - 8)
+
+/** The object cannot be written that because it's missing internal data */
+#define GIT_EMISSINGOBJDATA (GIT_ERROR - 9)
+
+/** The packfile for the ODB is corrupted */
+#define GIT_EPACKCORRUPTED (GIT_ERROR - 10)
+
+/** Failed to adquire or release a file lock */
+#define GIT_EFLOCKFAIL (GIT_ERROR - 11)
+
+/** The Z library failed to inflate/deflate an object's data */
+#define GIT_EZLIB (GIT_ERROR - 12)
+
+/** The queried object is currently busy */
+#define GIT_EBUSY (GIT_ERROR - 13)
+
+/** The index file is not backed up by an existing repository */
+#define GIT_EBAREINDEX (GIT_ERROR - 14)
+
+/** The name of the reference is not valid */
+#define GIT_EINVALIDREFNAME (GIT_ERROR - 15)
+
+/** The specified reference has its data corrupted */
+#define GIT_EREFCORRUPTED  (GIT_ERROR - 16)
+
+/** The specified symbolic reference is too deeply nested */
+#define GIT_ETOONESTEDSYMREF (GIT_ERROR - 17)
+
+/** The pack-refs file is either corrupted of its format is not currently supported */
+#define GIT_EPACKEDREFSCORRUPTED (GIT_ERROR - 18)
+
+/** The path is invalid */
+#define GIT_EINVALIDPATH (GIT_ERROR - 19)
+
+/** The revision walker is empty; there are no more commits left to iterate */
+#define GIT_EREVWALKOVER (GIT_ERROR - 20)
+
+/** The state of the reference is not valid */
+#define GIT_EINVALIDREFSTATE (GIT_ERROR - 21)
+
+GIT_BEGIN_DECL
+
+typedef struct {
+	char **strings;
+	size_t count;
+} git_strarray;
+
+GIT_EXTERN(void) git_strarray_free(git_strarray *array);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/errors.h b/libgit2/include/git2/errors.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/errors.h
@@ -0,0 +1,45 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_errors_h__
+#define INCLUDE_git_errors_h__
+
+/**
+ * @file git2/errors.h
+ * @brief Git error handling routines and variables
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * strerror() for the Git library
+ * @param num The error code to explain
+ * @return a string explaining the error code
+ */
+GIT_EXTERN(const char *) git_strerror(int num);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/index.h b/libgit2/include/git2/index.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/index.h
@@ -0,0 +1,199 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_index_h__
+#define INCLUDE_git_index_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+
+/**
+ * @file git2/index.h
+ * @brief Git index parsing and manipulation routines
+ * @defgroup git_index Git index parsing and manipulation routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+#define GIT_IDXENTRY_NAMEMASK  (0x0fff)
+#define GIT_IDXENTRY_STAGEMASK (0x3000)
+#define GIT_IDXENTRY_EXTENDED  (0x4000)
+#define GIT_IDXENTRY_VALID     (0x8000)
+#define GIT_IDXENTRY_STAGESHIFT 12
+
+/** Time used in a git index entry */
+typedef struct {
+	git_time_t seconds;
+	/* nsec should not be stored as time_t compatible */
+	unsigned int nanoseconds;
+} git_index_time;
+
+/** Memory representation of a file entry in the index. */
+typedef struct git_index_entry {
+	git_index_time ctime;
+	git_index_time mtime;
+
+	unsigned int dev;
+	unsigned int ino;
+	unsigned int mode;
+	unsigned int uid;
+	unsigned int gid;
+	git_off_t file_size;
+
+	git_oid oid;
+
+	unsigned short flags;
+	unsigned short flags_extended;
+
+	char *path;
+} git_index_entry;
+
+
+/**
+ * Create a new Git index object as a memory representation
+ * of the Git index file in 'index_path', without a repository
+ * to back it.
+ *
+ * Since there is no ODB behind this index, any Index methods
+ * which rely on the ODB (e.g. index_add) will fail with the
+ * GIT_EBAREINDEX error code.
+ *
+ * @param index the pointer for the new index
+ * @param index_path the path to the index file in disk
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_index_open_bare(git_index **index, const char *index_path);
+
+/**
+ * Open the Index inside the git repository pointed
+ * by 'repo'.
+ *
+ * @param repo the git repo which owns the index
+ * @param index_path the path to the index file in disk
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_index_open_inrepo(git_index **index, git_repository *repo);
+
+/**
+ * Clear the contents (all the entries) of an index object.
+ * This clears the index object in memory; changes must be manually
+ * written to disk for them to take effect.
+ *
+ * @param index an existing index object
+ */
+GIT_EXTERN(void) git_index_clear(git_index *index);
+
+/**
+ * Free an existing index object.
+ *
+ * @param index an existing index object
+ */
+GIT_EXTERN(void) git_index_free(git_index *index);
+
+/**
+ * Update the contents of an existing index object in memory
+ * by reading from the hard disk.
+ *
+ * @param index an existing index object
+ * @return 0 on success, otherwise an error code
+ */
+GIT_EXTERN(int) git_index_read(git_index *index);
+
+/**
+ * Write an existing index object from memory back to disk
+ * using an atomic file lock.
+ *
+ * @param index an existing index object
+ * @return 0 on success, otherwise an error code
+ */
+GIT_EXTERN(int) git_index_write(git_index *index);
+
+/**
+ * Find the first index of any entires which point to given
+ * path in the Git index.
+ *
+ * @param index an existing index object
+ * @param path path to search
+ * @return an index >= 0 if found, -1 otherwise
+ */
+GIT_EXTERN(int) git_index_find(git_index *index, const char *path);
+
+/**
+ * Add or update an index entry from a file in disk.
+ *
+ * @param index an existing index object
+ * @param path filename to add
+ * @param stage stage for the entry
+ * @return 0 on success, otherwise an error code
+ */
+GIT_EXTERN(int) git_index_add(git_index *index, const char *path, int stage);
+
+/**
+ * Remove an entry from the index 
+ *
+ * @param index an existing index object
+ * @param position position of the entry to remove
+ * @return 0 on success, otherwise an error code
+ */
+GIT_EXTERN(int) git_index_remove(git_index *index, int position);
+
+/**
+ * Insert an entry into the index.
+ * A full copy (including the 'path' string) of the given
+ * 'source_entry' will be inserted on the index; if the index
+ * already contains an entry for the same path, the entry
+ * will be updated.
+ *
+ * @param index an existing index object
+ * @param source_entry new entry object
+ * @return 0 on success, otherwise an error code
+ */
+GIT_EXTERN(int) git_index_insert(git_index *index, const git_index_entry *source_entry);
+
+/**
+ * Get a pointer to one of the entries in the index
+ *
+ * This entry can be modified, and the changes will be written
+ * back to disk on the next write() call.
+ *
+ * @param index an existing index object
+ * @param n the position of the entry
+ * @return a pointer to the entry; NULL if out of bounds
+ */
+GIT_EXTERN(git_index_entry *) git_index_get(git_index *index, int n);
+
+/**
+ * Get the count of entries currently in the index
+ *
+ * @param index an existing index object
+ * @return integer of count of current entries
+ */
+GIT_EXTERN(unsigned int) git_index_entrycount(git_index *index);
+
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/object.h b/libgit2/include/git2/object.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/object.h
@@ -0,0 +1,198 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_object_h__
+#define INCLUDE_git_object_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+
+/**
+ * @file git2/object.h
+ * @brief Git revision object management routines
+ * @defgroup git_object Git revision object management routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Lookup a reference to one of the objects in a repostory.
+ *
+ * The generated reference is owned by the repository and
+ * should not be freed by the user.
+ *
+ * The 'type' parameter must match the type of the object
+ * in the odb; the method will fail otherwise.
+ * The special value 'GIT_OBJ_ANY' may be passed to let
+ * the method guess the object's type.
+ *
+ * @param object pointer to the looked-up object
+ * @param repo the repository to look up the object
+ * @param id the unique identifier for the object
+ * @param type the type of the object
+ * @return a reference to the object
+ */
+GIT_EXTERN(int) git_object_lookup(git_object **object, git_repository *repo, const git_oid *id, git_otype type);
+
+/**
+ * Create a new in-memory repository object with
+ * the given type.
+ *
+ * The object's attributes can be filled in using the
+ * corresponding setter methods.
+ *
+ * The object will be written back to given git_repository
+ * when the git_object_write() function is called; objects
+ * cannot be written to disk until all their main
+ * attributes have been properly filled.
+ *
+ * Objects are instantiated with no SHA1 id; their id
+ * will be automatically generated when writing to the
+ * repository.
+ *
+ * @param object pointer to the new object
+ * @parem repo Repository where the object belongs
+ * @param type Type of the object to be created
+ * @return the new object
+ */
+GIT_EXTERN(int) git_object_new(git_object **object, git_repository *repo, git_otype type);
+
+
+/**
+ * Write back an object to disk.
+ *
+ * The object will be written to its corresponding
+ * repository.
+ *
+ * If the object has no changes since it was first
+ * read from the repository, no actions will take place.
+ *
+ * If the object has been modified since it was read from
+ * the repository, or it has been created from scratch
+ * in memory, it will be written to the repository and
+ * its SHA1 ID will be updated accordingly.
+ *
+ * @param object Git object to write back
+ * @return 0 on success; otherwise an error code
+ */
+GIT_EXTERN(int) git_object_write(git_object *object);
+
+/**
+ * Get the id (SHA1) of a repository object
+ *
+ * In-memory objects created by git_object_new() do not
+ * have a SHA1 ID until they are written on a repository.
+ *
+ * @param obj the repository object
+ * @return the SHA1 id
+ */
+GIT_EXTERN(const git_oid *) git_object_id(const git_object *obj);
+
+/**
+ * Get the object type of an object
+ *
+ * @param obj the repository object
+ * @return the object's type
+ */
+GIT_EXTERN(git_otype) git_object_type(const git_object *obj);
+
+/**
+ * Get the repository that owns this object
+ *
+ * @param obj the object
+ * @return the repository who owns this object
+ */
+GIT_EXTERN(git_repository *) git_object_owner(const git_object *obj);
+
+/**
+ * Close an open object
+ *
+ * This method instructs the library to close an existing
+ * object; note that git_objects are owned and cached by the repository
+ * so the object may or may not be freed after this library call,
+ * depending on how agressive is the caching mechanism used
+ * by the repository.
+ *
+ * IMPORTANT:
+ * It is *not* necessary to call this method when you stop using
+ * an object, since all object memory is automatically reclaimed
+ * by the repository when it is freed.
+ *
+ * Forgetting to call `git_object_close` does not cause memory
+ * leaks, but it's is recommended to close as soon as possible
+ * the biggest objects (e.g. blobs) to prevent wasting memory
+ * space.
+ *
+ * @param object the object to close
+ */
+GIT_EXTERN(void) git_object_close(git_object *object);
+
+/**
+ * Convert an object type to it's string representation.
+ *
+ * The result is a pointer to a string in static memory and
+ * should not be free()'ed.
+ *
+ * @param type object type to convert.
+ * @return the corresponding string representation.
+ */
+GIT_EXTERN(const char *) git_object_type2string(git_otype type);
+
+/**
+ * Convert a string object type representation to it's git_otype.
+ *
+ * @param str the string to convert.
+ * @return the corresponding git_otype.
+ */
+GIT_EXTERN(git_otype) git_object_string2type(const char *str);
+
+/**
+ * Determine if the given git_otype is a valid loose object type.
+ *
+ * @param type object type to test.
+ * @return true if the type represents a valid loose object type,
+ * false otherwise.
+ */
+GIT_EXTERN(int) git_object_typeisloose(git_otype type);
+
+/**
+ * Get the size in bytes for the structure which
+ * acts as an in-memory representation of any given
+ * object type.
+ *
+ * For all the core types, this would the equivalent
+ * of calling `sizeof(git_commit)` if the core types
+ * were not opaque on the external API.
+ *
+ * @param type object type to get its size
+ * @return size in bytes of the object
+ */
+GIT_EXTERN(size_t) git_object__size(git_otype type);
+
+/** @} */
+GIT_END_DECL
+
+#endif
diff --git a/libgit2/include/git2/odb.h b/libgit2/include/git2/odb.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/odb.h
@@ -0,0 +1,201 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_odb_h__
+#define INCLUDE_git_odb_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+
+/**
+ * @file git2/odb.h
+ * @brief Git object database routines
+ * @defgroup git_odb Git object database routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Create a new object database with no backends.
+ *
+ * Before the ODB can be used for read/writing, a custom database
+ * backend must be manually added using `git_odb_add_backend()`
+ *
+ * @param out location to store the database pointer, if opened.
+ *            Set to NULL if the open failed.
+ * @return GIT_SUCCESS if the database was created; otherwise an error
+ *         code describing why the open was not possible.
+ */
+GIT_EXTERN(int) git_odb_new(git_odb **out);
+
+/**
+ * Create a new object database and automatically add
+ * the two default backends:
+ *
+ *	- git_odb_backend_loose: read and write loose object files
+ *		from disk, assuming `objects_dir` as the Objects folder
+ *
+ *	- git_odb_backend_pack: read objects from packfiles,
+ *		assuming `objects_dir` as the Objects folder which
+ *		contains a 'pack/' folder with the corresponding data
+ *
+ * @param out location to store the database pointer, if opened.
+ *            Set to NULL if the open failed.
+ * @param objects_dir path of the backends' "objects" directory.
+ * @return GIT_SUCCESS if the database opened; otherwise an error
+ *         code describing why the open was not possible.
+ */
+GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
+
+/**
+ * Add a custom backend to an existing Object DB
+ *
+ * Read <odb_backends.h> for more information.
+ *
+ * @param odb database to add the backend to
+ * @paramm backend pointer to a git_odb_backend instance
+ * @return 0 on sucess; error code otherwise
+ */
+GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority);
+
+/**
+ * Add a custom backend to an existing Object DB; this
+ * backend will work as an alternate.
+ *
+ * Alternate backends are always checked for objects *after*
+ * all the main backends have been exhausted.
+ *
+ * Writing is disabled on alternate backends.
+ *
+ * Read <odb_backends.h> for more information.
+ *
+ * @param odb database to add the backend to
+ * @paramm backend pointer to a git_odb_backend instance
+ * @return 0 on sucess; error code otherwise
+ */
+GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority);
+
+/**
+ * Close an open object database.
+ * @param db database pointer to close.  If NULL no action is taken.
+ */
+GIT_EXTERN(void) git_odb_close(git_odb *db);
+
+/** An object read from the database. */
+typedef struct {
+	void *data;          /**< Raw, decompressed object data. */
+	size_t len;          /**< Total number of bytes in data. */
+	git_otype type;      /**< Type of this object. */
+} git_rawobj;
+
+/**
+ * Read an object from the database.
+ *
+ * If GIT_ENOTFOUND then out->data is set to NULL.
+ *
+ * @param out object descriptor to populate upon reading.
+ * @param db database to search for the object in.
+ * @param id identity of the object to read.
+ * @return
+ * - GIT_SUCCESS if the object was read;
+ * - GIT_ENOTFOUND if the object is not in the database.
+ */
+GIT_EXTERN(int) git_odb_read(git_rawobj *out, git_odb *db, const git_oid *id);
+
+/**
+ * Read the header of an object from the database, without
+ * reading its full contents.
+ *
+ * Only the 'type' and 'len' fields of the git_rawobj structure
+ * are filled. The 'data' pointer will always be NULL.
+ *
+ * The raw object pointed by 'out' doesn't need to be manually
+ * closed with git_rawobj_close().
+ *
+ * @param out object descriptor to populate upon reading.
+ * @param db database to search for the object in.
+ * @param id identity of the object to read.
+ * @return
+ * - GIT_SUCCESS if the object was read;
+ * - GIT_ENOTFOUND if the object is not in the database.
+ */
+GIT_EXTERN(int) git_odb_read_header(git_rawobj *out, git_odb *db, const git_oid *id);
+
+/**
+ * Write an object to the database.
+ *
+ * @param id identity of the object written.
+ * @param db database to which the object should be written.
+ * @param obj object descriptor for the object to write.
+ * @return
+ * - GIT_SUCCESS if the object was written;
+ * - GIT_ERROR otherwise.
+ */
+GIT_EXTERN(int) git_odb_write(git_oid *id, git_odb *db, git_rawobj *obj);
+
+/**
+ * Determine if the given object can be found in the object database.
+ *
+ * @param db database to be searched for the given object.
+ * @param id the object to search for.
+ * @return
+ * - true, if the object was found
+ * - false, otherwise
+ */
+GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
+
+
+
+
+
+/**
+ * Determine the object-ID (sha1 hash) of the given git_rawobj.
+ *
+ * The input obj must be a valid loose object type and the data
+ * pointer must not be NULL, unless the len field is also zero.
+ *
+ * @param id the resulting object-ID.
+ * @param obj the object whose hash is to be determined.
+ * @return
+ * - GIT_SUCCESS if the object-ID was correctly determined.
+ * - GIT_ERROR if the given object is malformed.
+ */
+GIT_EXTERN(int) git_rawobj_hash(git_oid *id, git_rawobj *obj);
+
+/**
+ * Release all memory used by the obj structure.
+ *
+ * As a result of this call, obj->data will be set to NULL.
+ *
+ * If obj->data is already NULL, nothing happens.
+ *
+ * @param obj object descriptor to free.
+ */
+GIT_EXTERN(void) git_rawobj_close(git_rawobj *obj);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/odb_backend.h b/libgit2/include/git2/odb_backend.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/odb_backend.h
@@ -0,0 +1,77 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_odb_backend_h__
+#define INCLUDE_git_odb_backend_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+#include "odb.h"
+
+/**
+ * @file git2/backend.h
+ * @brief Git custom backend functions
+ * @defgroup git_backend Git custom backend API
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/** An instance for a custom backend */
+struct git_odb_backend {
+	git_odb *odb;
+
+	int (* read)(
+			git_rawobj *,
+			struct git_odb_backend *,
+			const git_oid *);
+
+	int (* read_header)(
+			git_rawobj *,
+			struct git_odb_backend *,
+			const git_oid *);
+
+	int (* write)(
+			git_oid *id,
+			struct git_odb_backend *,
+			git_rawobj *obj);
+
+	int (* exists)(
+			struct git_odb_backend *,
+			const git_oid *);
+
+	void (* free)(struct git_odb_backend *);
+};
+
+GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir);
+GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir);
+
+#ifdef GIT2_SQLITE_BACKEND
+GIT_EXTERN(int) git_odb_backend_sqlite(git_odb_backend **backend_out, const char *sqlite_db);
+#endif
+
+GIT_END_DECL
+
+#endif
diff --git a/libgit2/include/git2/oid.h b/libgit2/include/git2/oid.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/oid.h
@@ -0,0 +1,191 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_oid_h__
+#define INCLUDE_git_oid_h__
+
+#include "common.h"
+#include "types.h"
+
+/**
+ * @file git2/oid.h
+ * @brief Git object id routines
+ * @defgroup git_oid Git object id routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/** Size (in bytes) of a raw/binary oid */
+#define GIT_OID_RAWSZ 20
+
+/** Size (in bytes) of a hex formatted oid */
+#define GIT_OID_HEXSZ (GIT_OID_RAWSZ * 2)
+
+/** Unique identity of any object (commit, tree, blob, tag). */
+typedef struct {
+	/** raw binary formatted id */
+	unsigned char id[GIT_OID_RAWSZ];
+} git_oid;
+
+/**
+ * Parse a hex formatted object id into a git_oid.
+ * @param out oid structure the result is written into.
+ * @param str input hex string; must be pointing at the start of
+ *        the hex sequence and have at least the number of bytes
+ *        needed for an oid encoded in hex (40 bytes).
+ * @return GIT_SUCCESS if valid; GIT_ENOTOID on failure.
+ */
+GIT_EXTERN(int) git_oid_mkstr(git_oid *out, const char *str);
+
+/**
+ * Copy an already raw oid into a git_oid structure.
+ * @param out oid structure the result is written into.
+ * @param raw the raw input bytes to be copied.
+ */
+GIT_EXTERN(void) git_oid_mkraw(git_oid *out, const unsigned char *raw);
+
+/**
+ * Format a git_oid into a hex string.
+ * @param str output hex string; must be pointing at the start of
+ *        the hex sequence and have at least the number of bytes
+ *        needed for an oid encoded in hex (40 bytes).  Only the
+ *        oid digits are written; a '\\0' terminator must be added
+ *        by the caller if it is required.
+ * @param oid oid structure to format.
+ */
+GIT_EXTERN(void) git_oid_fmt(char *str, const git_oid *oid);
+
+/**
+ * Format a git_oid into a loose-object path string.
+ * <p>
+ * The resulting string is "aa/...", where "aa" is the first two
+ * hex digitis of the oid and "..." is the remaining 38 digits.
+ *
+ * @param str output hex string; must be pointing at the start of
+ *        the hex sequence and have at least the number of bytes
+ *        needed for an oid encoded in hex (41 bytes).  Only the
+ *        oid digits are written; a '\\0' terminator must be added
+ *        by the caller if it is required.
+ * @param oid oid structure to format.
+ */
+GIT_EXTERN(void) git_oid_pathfmt(char *str, const git_oid *oid);
+
+/**
+ * Format a gid_oid into a newly allocated c-string.
+ * @param oid the oid structure to format
+ * @return the c-string; NULL if memory is exhausted.  Caller must
+ *         deallocate the string with free().
+ */
+GIT_EXTERN(char *) git_oid_allocfmt(const git_oid *oid);
+
+/**
+ * Format a git_oid into a buffer as a hex format c-string.
+ * <p>
+ * If the buffer is smaller than GIT_OID_HEXSZ+1, then the resulting
+ * oid c-string will be truncated to n-1 characters. If there are
+ * any input parameter errors (out == NULL, n == 0, oid == NULL),
+ * then a pointer to an empty string is returned, so that the return
+ * value can always be printed.
+ *
+ * @param out the buffer into which the oid string is output.
+ * @param n the size of the out buffer.
+ * @param oid the oid structure to format.
+ * @return the out buffer pointer, assuming no input parameter
+ *         errors, otherwise a pointer to an empty string.
+ */
+GIT_EXTERN(char *) git_oid_to_string(char *out, size_t n, const git_oid *oid);
+
+/**
+ * Copy an oid from one structure to another.
+ * @param out oid structure the result is written into.
+ * @param src oid structure to copy from.
+ */
+GIT_EXTERN(void) git_oid_cpy(git_oid *out, const git_oid *src);
+
+/**
+ * Compare two oid structures.
+ * @param a first oid structure.
+ * @param b second oid structure.
+ * @return <0, 0, >0 if a < b, a == b, a > b.
+ */
+GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b);
+
+/**
+ * OID Shortener object
+ */
+typedef struct git_oid_shorten git_oid_shorten;
+
+/**
+ * Create a new OID shortener.
+ *
+ * The OID shortener is used to process a list of OIDs
+ * in text form and return the shortest length that would
+ * uniquely identify all of them.
+ *
+ * E.g. look at the result of `git log --abbrev`.
+ *
+ * @param min_length The minimal length for all identifiers,
+ *		which will be used even if shorter OIDs would still
+ *		be unique.
+ *	@return a `git_oid_shorten` instance, NULL if OOM
+ */
+git_oid_shorten *git_oid_shorten_new(size_t min_length);
+
+/**
+ * Add a new OID to set of shortened OIDs and calculate
+ * the minimal length to uniquely identify all the OIDs in
+ * the set.
+ *
+ * The OID is expected to be a 40-char hexadecimal string.
+ * The OID is owned by the user and will not be modified
+ * or freed.
+ *
+ * For performance reasons, there is a hard-limit of how many
+ * OIDs can be added to a single set (around ~22000, assuming
+ * a mostly randomized distribution), which should be enough
+ * for any kind of program, and keeps the algorithm fast and
+ * memory-efficient.
+ *
+ * Attempting to add more than those OIDs will result in a
+ * GIT_ENOMEM error
+ *
+ * @param os a `git_oid_shorten` instance
+ * @param text_oid an OID in text form
+ * @return the minimal length to uniquely identify all OIDs
+ *		added so far to the set; or an error code (<0) if an
+ *		error occurs.
+ */
+int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid);
+
+/**
+ * Free an OID shortener instance
+ * 
+ * @param os a `git_oid_shorten` instance
+ */
+void git_oid_shorten_free(git_oid_shorten *os);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/refs.h b/libgit2/include/git2/refs.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/refs.h
@@ -0,0 +1,246 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_refs_h__
+#define INCLUDE_git_refs_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+
+/**
+ * @file git2/refs.h
+ * @brief Git reference management routines
+ * @defgroup git_reference Git reference management routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Lookup a reference by its name in a repository.
+ *
+ * The generated reference is owned by the repository and
+ * should not be freed by the user.
+ *
+ * @param reference_out pointer to the looked-up reference
+ * @param repo the repository to look up the reference
+ * @param name the long name for the reference (e.g. HEAD, ref/heads/master, refs/tags/v0.1.0, ...)
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_lookup(git_reference **reference_out, git_repository *repo, const char *name);
+
+/**
+ * Create a new symbolic reference.
+ *
+ * The reference will be created in the repository and written
+ * to the disk.
+ *
+ * This reference is owned by the repository and shall not
+ * be free'd by the user.
+ *
+ * @param ref_out Pointer to the newly created reference
+ * @param repo Repository where that reference will live
+ * @param name The name of the reference
+ * @param target The target of the reference
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target);
+
+/**
+ * Create a new object id reference.
+ *
+ * The reference will be created in the repository and written
+ * to the disk.
+ *
+ * This reference is owned by the repository and shall not
+ * be free'd by the user.
+ *
+ * @param ref_out Pointer to the newly created reference
+ * @param repo Repository where that reference will live
+ * @param name The name of the reference
+ * @param id The object id pointed to by the reference.
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id);
+
+/**
+ * Get the OID pointed to by a reference.
+ * 
+ * Only available if the reference is direct (i.e. not symbolic)
+ *
+ * @param ref The reference
+ * @return a pointer to the oid if available, NULL otherwise
+ */
+GIT_EXTERN(const git_oid *) git_reference_oid(git_reference *ref);
+
+/**
+ * Get full name to the reference pointed by this reference
+ * 
+ * Only available if the reference is symbolic
+ *
+ * @param ref The reference
+ * @return a pointer to the name if available, NULL otherwise
+ */
+GIT_EXTERN(const char *) git_reference_target(git_reference *ref);
+
+/**
+ * Get the type of a reference
+ *
+ * Either direct (GIT_REF_OID) or symbolic (GIT_REF_SYMBOLIC)
+ *
+ * @param ref The reference
+ * @return the type
+ */
+GIT_EXTERN(git_rtype) git_reference_type(git_reference *ref);
+
+/**
+ * Get the full name of a reference
+ *
+ * @param ref The reference
+ * @return the full name for the ref
+ */
+GIT_EXTERN(const char *) git_reference_name(git_reference *ref);
+
+/**
+ * Resolve a symbolic reference 
+ *
+ * Thie method iteratively peels a symbolic reference
+ * until it resolves to a direct reference to an OID.
+ *
+ * If a direct reference is passed as an argument,
+ * that reference is returned immediately
+ *
+ * @param resolved_ref Pointer to the peeled reference
+ * @param ref The reference
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_resolve(git_reference **resolved_ref, git_reference *ref);
+
+/**
+ * Get the repository where a reference resides
+ *
+ * @param ref The reference
+ * @return a pointer to the repo
+ */
+GIT_EXTERN(git_repository *) git_reference_owner(git_reference *ref);
+
+/**
+ * Set the symbolic target of a reference.
+ *
+ * The reference must be a symbolic reference, otherwise
+ * this method will fail.
+ *
+ * The reference will be automatically updated in
+ * memory and on disk.
+ *
+ * @param ref The reference
+ * @param target The new target for the reference
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_set_target(git_reference *ref, const char *target);
+
+/**
+ * Set the OID target of a reference.
+ *
+ * The reference must be a direct reference, otherwise
+ * this method will fail.
+ *
+ * The reference will be automatically updated in
+ * memory and on disk.
+ *
+ * @param ref The reference
+ * @param target The new target OID for the reference
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
+
+/**
+ * Rename an existing reference
+ *
+ * This method works for both direct and symbolic references.
+ * The new name will be checked for validity and may be
+ * modified into a normalized form.
+ *
+ * The refernece will be immediately renamed in-memory
+ * and on disk.
+ *
+ */
+GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name);
+
+/**
+ * Delete an existing reference
+ *
+ * This method works for both direct and symbolic references.
+ *
+ * The reference will be immediately removed on disk and from
+ * memory. The given reference pointer will no longer be valid.
+ *
+ */
+GIT_EXTERN(int) git_reference_delete(git_reference *ref);
+
+/**
+ * Pack all the loose references in the repository
+ *
+ * This method will load into the cache all the loose
+ * references on the repository and update the 
+ * `packed-refs` file with them.
+ *
+ * Once the `packed-refs` file has been written properly,
+ * the loose references will be removed from disk.
+ *
+ * WARNING: calling this method may invalidate any existing
+ * references previously loaded on the cache.
+ *
+ * @param repo Repository where the loose refs will be packed
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_packall(git_repository *repo);
+
+/**
+ * Fill a list with all the references that can be found
+ * in a repository.
+ *
+ * The listed references may be filtered by type, or using
+ * a bitwise OR of several types. Use the magic value
+ * `GIT_REF_LISTALL` to obtain all references, including
+ * packed ones.
+ *
+ * The string array will be filled with the names of all
+ * references; these values are owned by the user and
+ * should be free'd manually when no longer needed, using
+ * `git_strarray_free`.
+ *
+ * @param array Pointer to a git_strarray structure where
+ *		the reference names will be stored
+ * @param repo Repository where to find the refs
+ * @param list_flags Filtering flags for the reference
+ *		listing.
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/repository.h b/libgit2/include/git2/repository.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/repository.h
@@ -0,0 +1,191 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_repository_h__
+#define INCLUDE_git_repository_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+
+/**
+ * @file git2/repository.h
+ * @brief Git repository management routines
+ * @defgroup git_repository Git repository management routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Open a git repository.
+ *
+ * The 'path' argument must point to an existing git repository
+ * folder, e.g.
+ *
+ *		/path/to/my_repo/.git/	(normal repository)
+ *							objects/
+ *							index
+ *							HEAD
+ *
+ *		/path/to/bare_repo/		(bare repository)
+ *						objects/
+ *						index
+ *						HEAD
+ *
+ *	The method will automatically detect if 'path' is a normal
+ *	or bare repository or fail is 'path' is neither.
+ *
+ * @param repository pointer to the repo which will be opened
+ * @param path the path to the repository
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_repository_open(git_repository **repository, const char *path);
+
+
+/**
+ * Open a git repository by manually specifying all its paths
+ *
+ * @param repository pointer to the repo which will be opened
+ *
+ * @param git_dir The full path to the repository folder
+ *		e.g. a '.git' folder for live repos, any folder for bare
+ *		Equivalent to $GIT_DIR. 
+ *		Cannot be NULL.
+ *
+ * @param git_object_directory The full path to the ODB folder.
+ *		the folder where all the loose and packed objects are stored
+ *		Equivalent to $GIT_OBJECT_DIRECTORY.
+ *		If NULL, "$GIT_DIR/objects/" is assumed.
+ *
+ * @param git_index_file The full path to the index (dircache) file
+ *		Equivalent to $GIT_INDEX_FILE.
+ *		If NULL, "$GIT_DIR/index" is assumed.
+ *
+ * @param git_work_tree The full path to the working tree of the repository,
+ *		if the repository is not bare.
+ *		Equivalent to $GIT_WORK_TREE.
+ *		If NULL, the repository is assumed to be bare.
+ *
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_repository_open2(git_repository **repository,
+		const char *git_dir,
+		const char *git_object_directory,
+		const char *git_index_file,
+		const char *git_work_tree);
+
+
+/**
+ * Open a git repository by manually specifying its paths and
+ * the object database it will use.
+ *
+ * @param repository pointer to the repo which will be opened
+ *
+ * @param git_dir The full path to the repository folder
+ *		e.g. a '.git' folder for live repos, any folder for bare
+ *		Equivalent to $GIT_DIR. 
+ *		Cannot be NULL.
+ *
+ * @param object_database A pointer to a git_odb created & initialized
+ *		by the user (e.g. with custom backends). This object database
+ *		will be owned by the repository and will be automatically free'd.
+ *		It should not be manually free'd by the user, or this
+ *		git_repository object will become invalid.
+ *
+ * @param git_index_file The full path to the index (dircache) file
+ *		Equivalent to $GIT_INDEX_FILE.
+ *		If NULL, "$GIT_DIR/index" is assumed.
+ *
+ * @param git_work_tree The full path to the working tree of the repository,
+ *		if the repository is not bare.
+ *		Equivalent to $GIT_WORK_TREE.
+ *		If NULL, the repository is assumed to be bare.
+ *
+ * @return 0 on success; error code otherwise
+ */
+
+GIT_EXTERN(int) git_repository_open3(git_repository **repository,
+		const char *git_dir,
+		git_odb *object_database,
+		const char *git_index_file,
+		const char *git_work_tree);
+
+/**
+ * Get the object database behind a Git repository
+ *
+ * @param repo a repository object
+ * @return a pointer to the object db
+ */
+GIT_EXTERN(git_odb *) git_repository_database(git_repository *repo);
+
+/**
+ * Get the Index file of a Git repository
+ *
+ * This is a cheap operation; the index is only opened on the first call,
+ * and subsequent calls only retrieve the previous pointer.
+ *
+ * @param index Pointer where to store the index
+ * @param repo a repository object
+ * @return 0 on success; error code if the index could not be opened
+ */
+GIT_EXTERN(int) git_repository_index(git_index **index, git_repository *repo);
+
+/**
+ * Free a previously allocated repository
+ *
+ * @param repo repository handle to close. If NULL nothing occurs.
+ */
+GIT_EXTERN(void) git_repository_free(git_repository *repo);
+
+/**
+ * Force a garbage collector pass on the repository
+ *
+ * This will force-free any cached objects that have been
+ * previously marked by the user as closed (`git_object_close`).
+ *
+ * @param repo repository handle to collect. If NULL nothing occurs.
+ */
+GIT_EXTERN(int) git_repository_gc(git_repository *repo);
+
+/**
+ * Creates a new Git repository in the given folder.
+ *
+ * TODO:
+ *	- Reinit the repository
+ *	- Create config files
+ *
+ * @param repo_out pointer to the repo which will be created or reinitialized
+ * @param path the path to the repository
+ * @param is_bare if true, a Git repository without a working directory is created 
+ *		at the pointed path. If false, provided path will be considered as the working 
+ *		directory into which the .git directory will be created.
+ *
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/revwalk.h b/libgit2/include/git2/revwalk.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/revwalk.h
@@ -0,0 +1,187 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_revwalk_h__
+#define INCLUDE_git_revwalk_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+
+/**
+ * @file git2/revwalk.h
+ * @brief Git revision traversal routines
+ * @defgroup git_revwalk Git revision traversal routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Sort the repository contents in no particular ordering;
+ * this sorting is arbitrary, implementation-specific
+ * and subject to change at any time.
+ * This is the default sorting for new walkers.
+ */
+#define GIT_SORT_NONE         (0)
+
+/**
+ * Sort the repository contents in topological order
+ * (parents before children); this sorting mode
+ * can be combined with time sorting.
+ */
+#define GIT_SORT_TOPOLOGICAL  (1 << 0)
+
+/**
+ * Sort the repository contents by commit time;
+ * this sorting mode can be combined with
+ * topological sorting.
+ */
+#define GIT_SORT_TIME         (1 << 1)
+
+/**
+ * Iterate through the repository contents in reverse
+ * order; this sorting mode can be combined with
+ * any of the above.
+ */
+#define GIT_SORT_REVERSE      (1 << 2)
+
+/**
+ * Allocate a new revision walker to iterate through a repo.
+ *
+ * This revision walker uses a custom memory pool and an internal
+ * commit cache, so it is relatively expensive to allocate.
+ *
+ * For maximum performance, this revision walker should be
+ * reused for different walks.
+ *
+ * This revision walker is *not* thread safe: it may only be
+ * used to walk a repository on a single thread; however,
+ * it is possible to have several revision walkers in
+ * several different threads walking the same repository.
+ *
+ * @param walker pointer to the new revision walker
+ * @param repo the repo to walk through
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_revwalk_new(git_revwalk **walker, git_repository *repo);
+
+/**
+ * Reset the revision walker for reuse.
+ *
+ * This will clear all the pushed and hidden commits, and
+ * leave the walker in a blank state (just like at
+ * creation) ready to receive new commit pushes and
+ * start a new walk.
+ *
+ * The revision walk is automatically reset when a walk
+ * is over.
+ *
+ * @param walker handle to reset.
+ */
+GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker);
+
+/**
+ * Mark a commit to start traversal from.
+ *
+ * The given OID must belong to a commit on the walked
+ * repository.
+ *
+ * The given commit will be used as one of the roots
+ * when starting the revision walk. At least one commit
+ * must be pushed the repository before a walk can
+ * be started.
+ *
+ * @param walker the walker being used for the traversal.
+ * @param oid the oid of the commit to start from.
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *oid);
+
+
+/**
+ * Mark a commit (and its ancestors) uninteresting for the output.
+ *
+ * The given OID must belong to a commit on the walked
+ * repository.
+ *
+ * The resolved commit and all its parents will be hidden from the
+ * output on the revision walk.
+ *
+ * @param walker the walker being used for the traversal.
+ * @param commit the commit that will be ignored during the traversal
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *oid);
+
+/**
+ * Get the next commit from the revision walk.
+ *
+ * The initial call to this method is *not* blocking when
+ * iterating through a repo with a time-sorting mode.
+ *
+ * Iterating with Topological or inverted modes makes the initial
+ * call blocking to preprocess the commit list, but this block should be
+ * mostly unnoticeable on most repositories (topological preprocessing
+ * times at 0.3s on the git.git repo).
+ *
+ * The revision walker is reset when the walk is over.
+ *
+ * @param oid Pointer where to store the oid of the next commit
+ * @param walk the walker to pop the commit from.
+ * @return GIT_SUCCESS if the next commit was found;
+ *	GIT_EREVWALKOVER if there are no commits left to iterate
+ */
+GIT_EXTERN(int) git_revwalk_next(git_oid *oid, git_revwalk *walk);
+
+/**
+ * Change the sorting mode when iterating through the
+ * repository's contents.
+ *
+ * Changing the sorting mode resets the walker.
+ *
+ * @param walk the walker being used for the traversal.
+ * @param sort_mode combination of GIT_SORT_XXX flags
+ */
+GIT_EXTERN(void) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode);
+
+/**
+ * Free a revision walker previously allocated.
+ *
+ * @param walk traversal handle to close.  If NULL nothing occurs.
+ */
+GIT_EXTERN(void) git_revwalk_free(git_revwalk *walk);
+
+/**
+ * Return the repository on which this walker
+ * is operating.
+ *
+ * @param walk the revision walker
+ * @return the repository being walked
+ */
+GIT_EXTERN(git_repository *) git_revwalk_repository(git_revwalk *walk);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/signature.h b/libgit2/include/git2/signature.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/signature.h
@@ -0,0 +1,70 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_signature_h__
+#define INCLUDE_git_signature_h__
+
+#include "common.h"
+#include "types.h"
+
+/**
+ * @file git2/signature.h
+ * @brief Git signature creation
+ * @defgroup git_signature Git signature creation
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Create a new action signature. The signature must be freed
+ * manually or using git_signature_free
+ *
+ * @name name of the person
+ * @email email of the person
+ * @time time when the action happened
+ * @offset timezone offset in minutes for the time
+ * @return the new sig, NULl on out of memory
+ */
+GIT_EXTERN(git_signature *) git_signature_new(const char *name, const char *email, time_t time, int offset);
+
+/**
+ * Create a copy of an existing signature.
+ *
+ * All internal strings are also duplicated.
+ * @sig signature to duplicated
+ * @return a copy of sig, NULL on out of memory
+ */
+GIT_EXTERN(git_signature *) git_signature_dup(const git_signature *sig);
+
+/**
+ * Free an existing signature
+ *
+ * @sig signature to free
+ */
+GIT_EXTERN(void) git_signature_free(git_signature *sig);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/tag.h b/libgit2/include/git2/tag.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/tag.h
@@ -0,0 +1,154 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_tag_h__
+#define INCLUDE_git_tag_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+#include "object.h"
+
+/**
+ * @file git2/tag.h
+ * @brief Git tag parsing routines
+ * @defgroup git_tag Git tag management
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Lookup a tag object from the repository.
+ * The generated tag object is owned by the revision
+ * repo and shall not be freed by the user.
+ *
+ * @param tag pointer to the looked up tag
+ * @param repo the repo to use when locating the tag.
+ * @param id identity of the tag to locate.
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_tag_lookup(git_tag **tag, git_repository *repo, const git_oid *id)
+{
+	return git_object_lookup((git_object **)tag, repo, id, (git_otype)GIT_OBJ_TAG);
+}
+
+/**
+ * Create a new in-memory git_tag.
+ *
+ * The tag object must be manually filled using
+ * setter methods before it can be written to its
+ * repository.
+ *
+ * @param tag pointer to the new tag
+ * @param repo The repository where the object will reside
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_tag_new(git_tag **tag, git_repository *repo)
+{
+	return git_object_new((git_object **)tag, repo, (git_otype)GIT_OBJ_TAG);
+}
+
+/**
+ * Get the id of a tag.
+ * @param tag a previously loaded tag.
+ * @return object identity for the tag.
+ */
+GIT_EXTERN(const git_oid *) git_tag_id(git_tag *tag);
+
+/**
+ * Get the tagged object of a tag
+ * @param target pointer where to store the target
+ * @param tag a previously loaded tag.
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(int) git_tag_target(git_object **target, git_tag *t);
+
+/**
+ * Get the OID of the tagged object of a tag
+ * @param tag a previously loaded tag.
+ * @return pointer to the OID
+ */
+GIT_EXTERN(const git_oid *) git_tag_target_oid(git_tag *t);
+
+/**
+ * Get the type of a tag's tagged object
+ * @param tag a previously loaded tag.
+ * @return type of the tagged object
+ */
+GIT_EXTERN(git_otype) git_tag_type(git_tag *t);
+
+/**
+ * Get the name of a tag
+ * @param tag a previously loaded tag.
+ * @return name of the tag
+ */
+GIT_EXTERN(const char *) git_tag_name(git_tag *t);
+
+/**
+ * Get the tagger (author) of a tag
+ * @param tag a previously loaded tag.
+ * @return reference to the tag's author
+ */
+GIT_EXTERN(const git_signature *) git_tag_tagger(git_tag *t);
+
+/**
+ * Get the message of a tag
+ * @param tag a previously loaded tag.
+ * @return message of the tag
+ */
+GIT_EXTERN(const char *) git_tag_message(git_tag *t);
+
+/**
+ * Set the target of a tag (i.e. the object that the tag points to)
+ * @param tag The tag to modify
+ * @param target the new tagged target
+ */
+GIT_EXTERN(int) git_tag_set_target(git_tag *tag, git_object *target);
+
+/**
+ * Set the name of a tag
+ * @param tag The tag to modify
+ * @param name the new name for the tag
+ */
+GIT_EXTERN(void) git_tag_set_name(git_tag *tag, const char *name);
+
+/**
+ * Set the tagger of a tag
+ * @param tag The tag to modify
+ * @param tagger_sig signature of the tagging action
+ * @return 0 on success; error code otherwise
+ */
+GIT_EXTERN(void) git_tag_set_tagger(git_tag *tag, const git_signature *tagger_sig);
+
+/**
+ * Set the message of a tag
+ * @param tag The tag to modify
+ * @param message the new tagger for the tag
+ */
+GIT_EXTERN(void) git_tag_set_message(git_tag *tag, const char *message);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/thread-utils.h b/libgit2/include/git2/thread-utils.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/thread-utils.h
@@ -0,0 +1,72 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_thread_utils_h__
+#define INCLUDE_git_thread_utils_h__
+
+/*
+ * How TLS works is compiler+platform dependant
+ * Sources: http://en.wikipedia.org/wiki/Thread-Specific_Storage
+ *          http://predef.sourceforge.net/precomp.html
+ */
+
+#define GIT_HAS_TLS 1
+
+#if defined(__APPLE__) && defined(__MACH__)
+# undef GIT_TLS
+
+#elif defined(__GNUC__) || \
+      defined(__SUNPRO_C) || \
+      defined(__SUNPRO_CC) || \
+      defined(__xlc__) || \
+      defined(__xlC__)
+# define GIT_TLS __thread
+
+#elif defined(__INTEL_COMPILER)
+# if defined(_WIN32) || defined(_WIN32_CE)
+#  define GIT_TLS __declspec(thread)
+# else
+#  define GIT_TLS __thread
+# endif
+
+#elif defined(_WIN32) || \
+      defined(_WIN32_CE) || \
+      defined(__BORLANDC__)
+# define GIT_TLS __declspec(thread)
+
+#else
+# undef GIT_HAS_TLS
+# define GIT_TLS /* nothing: tls vars are thread-global */
+#endif
+
+/* sparse and cygwin don't grok thread-local variables */
+#if defined(__CHECKER__) || defined(__CYGWIN__)
+# undef GIT_HAS_TLS
+# undef GIT_TLS
+# define GIT_TLS
+#endif
+
+#define GIT_THREADS 1
+
+#endif /* INCLUDE_git_thread_utils_h__ */
diff --git a/libgit2/include/git2/tree.h b/libgit2/include/git2/tree.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/tree.h
@@ -0,0 +1,223 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_tree_h__
+#define INCLUDE_git_tree_h__
+
+#include "common.h"
+#include "types.h"
+#include "oid.h"
+#include "object.h"
+
+/**
+ * @file git2/tree.h
+ * @brief Git tree parsing, loading routines
+ * @defgroup git_tree Git tree parsing, loading routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Lookup a tree object from the repository.
+ * The generated tree object is owned by the revision
+ * repo and shall not be freed by the user.
+ *
+ * @param tree pointer to the looked up tree
+ * @param repo the repo to use when locating the tree.
+ * @param id identity of the tree to locate.
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_tree_lookup(git_tree **tree, git_repository *repo, const git_oid *id)
+{
+	return git_object_lookup((git_object **)tree, repo, id, GIT_OBJ_TREE);
+}
+
+/**
+ * Create a new in-memory git_tree.
+ *
+ * The tree object must be manually filled using
+ * setter methods before it can be written to its
+ * repository.
+ *
+ * @param tree pointer to the new tree
+ * @param repo The repository where the object will reside
+ * @return 0 on success; error code otherwise
+ */
+GIT_INLINE(int) git_tree_new(git_tree **tree, git_repository *repo)
+{
+	return git_object_new((git_object **)tree, repo, GIT_OBJ_TREE);
+}
+
+/**
+ * Get the id of a tree.
+ * @param tree a previously loaded tree.
+ * @return object identity for the tree.
+ */
+GIT_EXTERN(const git_oid *) git_tree_id(git_tree *tree);
+
+
+/**
+ * Get the number of entries listed in a tree
+ * @param tree a previously loaded tree.
+ * @return the number of entries in the tree
+ */
+GIT_EXTERN(size_t) git_tree_entrycount(git_tree *tree);
+
+/**
+ * Lookup a tree entry by its filename
+ * @param tree a previously loaded tree.
+ * @param filename the filename of the desired entry
+ * @return the tree entry; NULL if not found
+ */
+GIT_EXTERN(git_tree_entry *) git_tree_entry_byname(git_tree *tree, const char *filename);
+
+/**
+ * Lookup a tree entry by its position in the tree
+ * @param tree a previously loaded tree.
+ * @param idx the position in the entry list
+ * @return the tree entry; NULL if not found
+ */
+GIT_EXTERN(git_tree_entry *) git_tree_entry_byindex(git_tree *tree, int idx);
+
+/**
+ * Get the UNIX file attributes of a tree entry
+ * @param entry a tree entry
+ * @return attributes as an integer
+ */
+GIT_EXTERN(unsigned int) git_tree_entry_attributes(git_tree_entry *entry);
+
+/**
+ * Get the filename of a tree entry
+ * @param entry a tree entry
+ * @return the name of the file
+ */
+GIT_EXTERN(const char *) git_tree_entry_name(git_tree_entry *entry);
+
+/**
+ * Get the id of the object pointed by the entry
+ * @param entry a tree entry
+ * @return the oid of the object
+ */
+GIT_EXTERN(const git_oid *) git_tree_entry_id(git_tree_entry *entry);
+
+/**
+ * Convert a tree entry to the git_object it points too.
+ *
+ * @param object pointer to the converted object
+ * @param entry a tree entry
+ * @return a reference to the pointed object in the repository
+ */
+GIT_EXTERN(int) git_tree_entry_2object(git_object **object, git_tree_entry *entry);
+
+/**
+ * Add a new entry to a tree and return the new entry.
+ *
+ * This will mark the tree as modified; the new entry will
+ * be written back to disk on the next git_object_write()
+ *
+ * @param entry_out Pointer to the entry that just got
+ *	created. May be NULL if you are not interested on
+ *	getting the new entry
+ * @param tree Tree object to store the entry
+ * @iparam id OID for the tree entry
+ * @param filename Filename for the tree entry
+ * @param attributes UNIX file attributes for the entry
+ * @return 0 on success; otherwise error code
+ */
+GIT_EXTERN(int) git_tree_add_entry(git_tree_entry **entry_out, git_tree *tree, const git_oid *id, const char *filename, int attributes);
+
+/**
+ * Remove an entry by its index.
+ *
+ * Index must be >= 0 and < than git_tree_entrycount().
+ *
+ * This will mark the tree as modified; the modified entry will
+ * be written back to disk on the next git_object_write()
+ *
+ * @param tree Tree where to remove the entry
+ * @param idx index of the entry
+ * @return 0 on successful removal; GIT_ENOTFOUND if the entry wasn't found
+ */
+GIT_EXTERN(int) git_tree_remove_entry_byindex(git_tree *tree, int idx);
+
+/**
+ * Remove an entry by its filename.
+ *
+ * This will mark the tree as modified; the modified entry will
+ * be written back to disk on the next git_object_write()
+ *
+ * @param tree Tree where to remove the entry
+ * @param filename File name of the entry
+ * @return 0 on successful removal; GIT_ENOTFOUND if the entry wasn't found
+ */
+GIT_EXTERN(int) git_tree_remove_entry_byname(git_tree *tree, const char *filename);
+
+/**
+ * Clear all the entries in a tree.
+ *
+ * This will mark the tree as modified; the modified entry will
+ * be written back to disk on the next git_object_write().
+ *
+ * @param tree Tree object whose entries are to be sorted
+ */
+GIT_EXTERN(void) git_tree_clear_entries(git_tree *tree);
+
+/**
+ * Change the SHA1 id of a tree entry.
+ *
+ * This will mark the tree that contains the entry as modified;
+ * the modified entry will be written back to disk on the next git_object_write()
+ *
+ * @param entry Entry object which will be modified
+ * @param oid new SHA1 oid for the entry
+ */
+GIT_EXTERN(void) git_tree_entry_set_id(git_tree_entry *entry, const git_oid *oid);
+
+/**
+ * Change the filename of a tree entry.
+ *
+ * This will mark the tree that contains the entry as modified;
+ * the modified entry will be written back to disk on the next git_object_write()
+ *
+ * @param entry Entry object which will be modified
+ * @param oid new filename for the entry
+ */
+GIT_EXTERN(void) git_tree_entry_set_name(git_tree_entry *entry, const char *name);
+
+/**
+ * Change the attributes of a tree entry.
+ *
+ * This will mark the tree that contains the entry as modified;
+ * the modified entry will be written back to disk on the next git_object_write()
+ *
+ * @param entry Entry object which will be modified
+ * @param oid new attributes for the entry
+ * @return 0 if the attributes were properly set; error code otherwise
+ */
+GIT_EXTERN(int) git_tree_entry_set_attributes(git_tree_entry *entry, unsigned int attr);
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/include/git2/types.h b/libgit2/include/git2/types.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/types.h
@@ -0,0 +1,154 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_types_h__
+#define INCLUDE_git_types_h__
+
+/**
+ * @file git2/types.h
+ * @brief libgit2 base & compatibility types
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+/**
+ * Cross-platform compatibility types for off_t / time_t
+ *
+ * NOTE: This needs to be in a public header so that both the library
+ * implementation and client applications both agree on the same types.
+ * Otherwise we get undefined behavior.
+ *
+ * Use the "best" types that each platform provides. Currently we truncate
+ * these intermediate representations for compatibility with the git ABI, but
+ * if and when it changes to support 64 bit types, our code will naturally
+ * adapt.
+ * NOTE: These types should match those that are returned by our internal
+ * stat() functions, for all platforms.
+ */
+#include <sys/types.h>
+
+#if defined(_MSC_VER)
+
+typedef __int64 git_off_t;
+typedef __time64_t git_time_t;
+
+#elif defined(__MINGW32__)
+
+typedef off64_t git_off_t;
+typedef time_t git_time_t;
+
+#else  /* POSIX */
+
+/* 
+ * Note: Can't use off_t since if a client program includes <sys/types.h>
+ * before us (directly or indirectly), they'll get 32 bit off_t in their client
+ * app, even though /we/ define _FILE_OFFSET_BITS=64.
+ */
+typedef long long git_off_t;
+typedef time_t git_time_t;
+
+#endif
+
+
+/** Basic type (loose or packed) of any Git object. */
+typedef enum {
+	GIT_OBJ_ANY = -2,		/**< Object can be any of the following */
+	GIT_OBJ_BAD = -1,       /**< Object is invalid. */
+	GIT_OBJ__EXT1 = 0,      /**< Reserved for future use. */
+	GIT_OBJ_COMMIT = 1,     /**< A commit object. */
+	GIT_OBJ_TREE = 2,       /**< A tree (directory listing) object. */
+	GIT_OBJ_BLOB = 3,       /**< A file revision object. */
+	GIT_OBJ_TAG = 4,        /**< An annotated tag object. */
+	GIT_OBJ__EXT2 = 5,      /**< Reserved for future use. */
+	GIT_OBJ_OFS_DELTA = 6,  /**< A delta, base is given by an offset. */
+	GIT_OBJ_REF_DELTA = 7,  /**< A delta, base is given by object id. */
+} git_otype;
+
+/** An open object database handle. */
+typedef struct git_odb git_odb;
+
+/** A custom backend in an ODB */
+typedef struct git_odb_backend git_odb_backend;
+
+/**
+ * Representation of an existing git repository,
+ * including all its object contents
+ */
+typedef struct git_repository git_repository;
+
+/** Representation of a generic object in a repository */
+typedef struct git_object git_object;
+
+/** Representation of an in-progress walk through the commits in a repo */
+typedef struct git_revwalk git_revwalk;
+
+/** Parsed representation of a tag object. */
+typedef struct git_tag git_tag;
+
+/** In-memory representation of a blob object. */
+typedef struct git_blob git_blob;
+
+/** Parsed representation of a commit object. */
+typedef struct git_commit git_commit;
+
+/** Representation of each one of the entries in a tree object. */
+typedef struct git_tree_entry git_tree_entry;
+
+/** Representation of a tree object. */
+typedef struct git_tree git_tree;
+
+/** Memory representation of an index file. */
+typedef struct git_index git_index;
+
+/** Time in a signature */
+typedef struct git_time {
+	time_t time; /** time in seconds from epoch */
+	int offset; /** timezone offset, in minutes */
+} git_time;
+
+/** An action signature (e.g. for committers, taggers, etc) */
+typedef struct git_signature {
+	char *name; /** full name of the author */
+	char *email; /** email of the author */
+	git_time when; /** time when the action happened */
+} git_signature;
+
+/** In-memory representation of a reference. */
+typedef struct git_reference git_reference;
+
+/** Basic type of any Git reference. */
+typedef enum {
+	GIT_REF_INVALID = 0, /** Invalid reference */
+	GIT_REF_OID = 1, /** A reference which points at an object id */
+	GIT_REF_SYMBOLIC = 2, /** A reference which points at another reference */
+	GIT_REF_PACKED = 4,
+	GIT_REF_HAS_PEEL = 8,
+	GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC|GIT_REF_PACKED,
+} git_rtype;
+
+/** @} */
+GIT_END_DECL
+
+#endif
diff --git a/libgit2/include/git2/zlib.h b/libgit2/include/git2/zlib.h
new file mode 100644
--- /dev/null
+++ b/libgit2/include/git2/zlib.h
@@ -0,0 +1,58 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDE_git_zlib_h__
+#define INCLUDE_git_zlib_h__
+
+#include <zlib.h>
+
+/**
+ * @file git2/zlib.h
+ * @brief Git data compression routines
+ * @defgroup git_zlib Git data compression routines
+ * @ingroup Git
+ * @{
+ */
+GIT_BEGIN_DECL
+
+#if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
+/**
+ * deflateBound returns an upper bound on the compressed size.
+ *
+ * This is a stub function used when zlib does not supply the
+ * deflateBound() implementation itself.
+ *
+ * @param stream the stream pointer.
+ * @param s total length of the source data (in bytes).
+ * @return maximum length of the compressed data.
+ */
+GIT_INLINE(size_t) deflateBound(z_streamp stream, size_t s)
+{
+	return (s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11);
+}
+#endif
+
+/** @} */
+GIT_END_DECL
+#endif
diff --git a/libgit2/src/blob.c b/libgit2/src/blob.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/blob.c
@@ -0,0 +1,136 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "git2/common.h"
+#include "git2/object.h"
+#include "git2/repository.h"
+
+#include "common.h"
+#include "blob.h"
+
+const void *git_blob_rawcontent(git_blob *blob)
+{
+	assert(blob);
+	
+	if (blob->content.data != NULL)
+		return blob->content.data;
+
+	if (blob->object.in_memory)
+		return NULL;
+
+	if (!blob->object.source.open && git_object__source_open((git_object *)blob) < GIT_SUCCESS)
+		return NULL;
+
+	return blob->object.source.raw.data;
+}
+
+int git_blob_rawsize(git_blob *blob)
+{
+	assert(blob);
+
+	if (blob->content.data != NULL)
+		return blob->content.len;
+
+	return blob->object.source.raw.len;
+}
+
+void git_blob__free(git_blob *blob)
+{
+	gitfo_free_buf(&blob->content);
+	free(blob);
+}
+
+int git_blob__parse(git_blob *blob)
+{
+	assert(blob);
+	return GIT_SUCCESS;
+}
+
+int git_blob__writeback(git_blob *blob, git_odb_source *src)
+{
+	assert(blob->object.modified);
+
+	if (blob->content.data == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	return git__source_write(src, blob->content.data, blob->content.len);
+}
+
+int git_blob_set_rawcontent(git_blob *blob, const void *buffer, size_t len)
+{
+	assert(blob && buffer);
+
+	blob->object.modified = 1;
+
+	git_object__source_close((git_object *)blob);
+
+	if (blob->content.data != NULL)
+		gitfo_free_buf(&blob->content);
+
+	blob->content.data = git__malloc(len);
+	blob->content.len = len;
+
+	if (blob->content.data == NULL)
+		return GIT_ENOMEM;
+
+	memcpy(blob->content.data, buffer, len);
+
+	return GIT_SUCCESS;
+}
+
+int git_blob_set_rawcontent_fromfile(git_blob *blob, const char *filename)
+{
+	assert(blob && filename);
+	blob->object.modified = 1;
+
+	if (blob->content.data != NULL)
+		gitfo_free_buf(&blob->content);
+
+	return gitfo_read_file(&blob->content, filename);
+}
+
+int git_blob_writefile(git_oid *written_id, git_repository *repo, const char *path)
+{
+	int error;
+	git_blob *blob;
+
+	if (gitfo_exists(path) < 0)
+		return GIT_ENOTFOUND;
+
+	if ((error = git_blob_new(&blob, repo)) < GIT_SUCCESS)
+		return error;
+
+	if ((error = git_blob_set_rawcontent_fromfile(blob, path)) < GIT_SUCCESS)
+		return error;
+
+	if ((error = git_object_write((git_object *)blob)) < GIT_SUCCESS)
+		return error;
+
+	git_oid_cpy(written_id, git_object_id((git_object *)blob));
+
+	git_object_close((git_object*)blob);
+	return GIT_SUCCESS;
+}
+
diff --git a/libgit2/src/blob.h b/libgit2/src/blob.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/blob.h
@@ -0,0 +1,17 @@
+#ifndef INCLUDE_blob_h__
+#define INCLUDE_blob_h__
+
+#include "git2/blob.h"
+#include "repository.h"
+#include "fileops.h"
+
+struct git_blob {
+	git_object object;
+	gitfo_buf content;
+};
+
+void git_blob__free(git_blob *blob);
+int git_blob__parse(git_blob *blob);
+int git_blob__writeback(git_blob *blob, git_odb_source *src);
+
+#endif
diff --git a/libgit2/src/block-sha1/sha1.c b/libgit2/src/block-sha1/sha1.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/block-sha1/sha1.c
@@ -0,0 +1,281 @@
+/*
+ * SHA1 routine optimized to do word accesses rather than byte accesses,
+ * and to avoid unnecessary copies into the context array.
+ *
+ * This was initially based on the Mozilla SHA1 implementation, although
+ * none of the original Mozilla code remains.
+ */
+
+#include "common.h"
+#include "sha1.h"
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+/*
+ * Force usage of rol or ror by selecting the one with the smaller constant.
+ * It _can_ generate slightly smaller code (a constant of 1 is special), but
+ * perhaps more importantly it's possibly faster on any uarch that does a
+ * rotate with a loop.
+ */
+
+#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
+#define SHA_ROL(x,n)	SHA_ASM("rol", x, n)
+#define SHA_ROR(x,n)	SHA_ASM("ror", x, n)
+
+#else
+
+#define SHA_ROT(X,l,r)	(((X) << (l)) | ((X) >> (r)))
+#define SHA_ROL(X,n)	SHA_ROT(X,n,32-(n))
+#define SHA_ROR(X,n)	SHA_ROT(X,32-(n),n)
+
+#endif
+
+/*
+ * If you have 32 registers or more, the compiler can (and should)
+ * try to change the array[] accesses into registers. However, on
+ * machines with less than ~25 registers, that won't really work,
+ * and at least gcc will make an unholy mess of it.
+ *
+ * So to avoid that mess which just slows things down, we force
+ * the stores to memory to actually happen (we might be better off
+ * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
+ * suggested by Artur Skawina - that will also make gcc unable to
+ * try to do the silly "optimize away loads" part because it won't
+ * see what the value will be).
+ *
+ * Ben Herrenschmidt reports that on PPC, the C version comes close
+ * to the optimized asm with this (ie on PPC you don't want that
+ * 'volatile', since there are lots of registers).
+ *
+ * On ARM we get the best code generation by forcing a full memory barrier
+ * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
+ * the stack frame size simply explode and performance goes down the drain.
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+  #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val))
+#elif defined(__GNUC__) && defined(__arm__)
+  #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
+#else
+  #define setW(x, val) (W(x) = (val))
+#endif
+
+/*
+ * Performance might be improved if the CPU architecture is OK with
+ * unaligned 32-bit loads and a fast ntohl() is available.
+ * Otherwise fall back to byte loads and shifts which is portable,
+ * and is faster on architectures with memory alignment issues.
+ */
+
+#if defined(__i386__) || defined(__x86_64__) || \
+    defined(_M_IX86) || defined(_M_X64) || \
+    defined(__ppc__) || defined(__ppc64__) || \
+    defined(__powerpc__) || defined(__powerpc64__) || \
+    defined(__s390__) || defined(__s390x__)
+
+#define get_be32(p)	ntohl(*(unsigned int *)(p))
+#define put_be32(p, v)	do { *(unsigned int *)(p) = htonl(v); } while (0)
+
+#else
+
+#define get_be32(p)	( \
+	(*((unsigned char *)(p) + 0) << 24) | \
+	(*((unsigned char *)(p) + 1) << 16) | \
+	(*((unsigned char *)(p) + 2) <<  8) | \
+	(*((unsigned char *)(p) + 3) <<  0) )
+#define put_be32(p, v)	do { \
+	unsigned int __v = (v); \
+	*((unsigned char *)(p) + 0) = __v >> 24; \
+	*((unsigned char *)(p) + 1) = __v >> 16; \
+	*((unsigned char *)(p) + 2) = __v >>  8; \
+	*((unsigned char *)(p) + 3) = __v >>  0; } while (0)
+
+#endif
+
+/* This "rolls" over the 512-bit array */
+#define W(x) (array[(x)&15])
+
+/*
+ * Where do we get the source from? The first 16 iterations get it from
+ * the input data, the next mix it from the 512-bit array.
+ */
+#define SHA_SRC(t) get_be32(data + t)
+#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
+
+#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
+	unsigned int TEMP = input(t); setW(t, TEMP); \
+	E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \
+	B = SHA_ROR(B, 2); } while (0)
+
+#define T_0_15(t, A, B, C, D, E)  SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
+#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
+#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) ,  0xca62c1d6, A, B, C, D, E )
+
+static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data)
+{
+	unsigned int A,B,C,D,E;
+	unsigned int array[16];
+
+	A = ctx->H[0];
+	B = ctx->H[1];
+	C = ctx->H[2];
+	D = ctx->H[3];
+	E = ctx->H[4];
+
+	/* Round 1 - iterations 0-16 take their input from 'data' */
+	T_0_15( 0, A, B, C, D, E);
+	T_0_15( 1, E, A, B, C, D);
+	T_0_15( 2, D, E, A, B, C);
+	T_0_15( 3, C, D, E, A, B);
+	T_0_15( 4, B, C, D, E, A);
+	T_0_15( 5, A, B, C, D, E);
+	T_0_15( 6, E, A, B, C, D);
+	T_0_15( 7, D, E, A, B, C);
+	T_0_15( 8, C, D, E, A, B);
+	T_0_15( 9, B, C, D, E, A);
+	T_0_15(10, A, B, C, D, E);
+	T_0_15(11, E, A, B, C, D);
+	T_0_15(12, D, E, A, B, C);
+	T_0_15(13, C, D, E, A, B);
+	T_0_15(14, B, C, D, E, A);
+	T_0_15(15, A, B, C, D, E);
+
+	/* Round 1 - tail. Input from 512-bit mixing array */
+	T_16_19(16, E, A, B, C, D);
+	T_16_19(17, D, E, A, B, C);
+	T_16_19(18, C, D, E, A, B);
+	T_16_19(19, B, C, D, E, A);
+
+	/* Round 2 */
+	T_20_39(20, A, B, C, D, E);
+	T_20_39(21, E, A, B, C, D);
+	T_20_39(22, D, E, A, B, C);
+	T_20_39(23, C, D, E, A, B);
+	T_20_39(24, B, C, D, E, A);
+	T_20_39(25, A, B, C, D, E);
+	T_20_39(26, E, A, B, C, D);
+	T_20_39(27, D, E, A, B, C);
+	T_20_39(28, C, D, E, A, B);
+	T_20_39(29, B, C, D, E, A);
+	T_20_39(30, A, B, C, D, E);
+	T_20_39(31, E, A, B, C, D);
+	T_20_39(32, D, E, A, B, C);
+	T_20_39(33, C, D, E, A, B);
+	T_20_39(34, B, C, D, E, A);
+	T_20_39(35, A, B, C, D, E);
+	T_20_39(36, E, A, B, C, D);
+	T_20_39(37, D, E, A, B, C);
+	T_20_39(38, C, D, E, A, B);
+	T_20_39(39, B, C, D, E, A);
+
+	/* Round 3 */
+	T_40_59(40, A, B, C, D, E);
+	T_40_59(41, E, A, B, C, D);
+	T_40_59(42, D, E, A, B, C);
+	T_40_59(43, C, D, E, A, B);
+	T_40_59(44, B, C, D, E, A);
+	T_40_59(45, A, B, C, D, E);
+	T_40_59(46, E, A, B, C, D);
+	T_40_59(47, D, E, A, B, C);
+	T_40_59(48, C, D, E, A, B);
+	T_40_59(49, B, C, D, E, A);
+	T_40_59(50, A, B, C, D, E);
+	T_40_59(51, E, A, B, C, D);
+	T_40_59(52, D, E, A, B, C);
+	T_40_59(53, C, D, E, A, B);
+	T_40_59(54, B, C, D, E, A);
+	T_40_59(55, A, B, C, D, E);
+	T_40_59(56, E, A, B, C, D);
+	T_40_59(57, D, E, A, B, C);
+	T_40_59(58, C, D, E, A, B);
+	T_40_59(59, B, C, D, E, A);
+
+	/* Round 4 */
+	T_60_79(60, A, B, C, D, E);
+	T_60_79(61, E, A, B, C, D);
+	T_60_79(62, D, E, A, B, C);
+	T_60_79(63, C, D, E, A, B);
+	T_60_79(64, B, C, D, E, A);
+	T_60_79(65, A, B, C, D, E);
+	T_60_79(66, E, A, B, C, D);
+	T_60_79(67, D, E, A, B, C);
+	T_60_79(68, C, D, E, A, B);
+	T_60_79(69, B, C, D, E, A);
+	T_60_79(70, A, B, C, D, E);
+	T_60_79(71, E, A, B, C, D);
+	T_60_79(72, D, E, A, B, C);
+	T_60_79(73, C, D, E, A, B);
+	T_60_79(74, B, C, D, E, A);
+	T_60_79(75, A, B, C, D, E);
+	T_60_79(76, E, A, B, C, D);
+	T_60_79(77, D, E, A, B, C);
+	T_60_79(78, C, D, E, A, B);
+	T_60_79(79, B, C, D, E, A);
+
+	ctx->H[0] += A;
+	ctx->H[1] += B;
+	ctx->H[2] += C;
+	ctx->H[3] += D;
+	ctx->H[4] += E;
+}
+
+void git__blk_SHA1_Init(blk_SHA_CTX *ctx)
+{
+	ctx->size = 0;
+
+	/* Initialize H with the magic constants (see FIPS180 for constants) */
+	ctx->H[0] = 0x67452301;
+	ctx->H[1] = 0xefcdab89;
+	ctx->H[2] = 0x98badcfe;
+	ctx->H[3] = 0x10325476;
+	ctx->H[4] = 0xc3d2e1f0;
+}
+
+void git__blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len)
+{
+	unsigned int lenW = ctx->size & 63;
+
+	ctx->size += len;
+
+	/* Read the data into W and process blocks as they get full */
+	if (lenW) {
+		unsigned int left = 64 - lenW;
+		if (len < left)
+			left = len;
+		memcpy(lenW + (char *)ctx->W, data, left);
+		lenW = (lenW + left) & 63;
+		len -= left;
+		data = ((const char *)data + left);
+		if (lenW)
+			return;
+		blk_SHA1_Block(ctx, ctx->W);
+	}
+	while (len >= 64) {
+		blk_SHA1_Block(ctx, data);
+		data = ((const char *)data + 64);
+		len -= 64;
+	}
+	if (len)
+		memcpy(ctx->W, data, len);
+}
+
+void git__blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx)
+{
+	static const unsigned char pad[64] = { 0x80 };
+	unsigned int padlen[2];
+	int i;
+
+	/* Pad with a binary 1 (ie 0x80), then zeroes, then length */
+	padlen[0] = htonl((uint32_t)(ctx->size >> 29));
+	padlen[1] = htonl((uint32_t)(ctx->size << 3));
+
+	i = ctx->size & 63;
+	git__blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i)));
+	git__blk_SHA1_Update(ctx, padlen, 8);
+
+	/* Output hash */
+	for (i = 0; i < 5; i++)
+		put_be32(hashout + i*4, ctx->H[i]);
+}
diff --git a/libgit2/src/block-sha1/sha1.h b/libgit2/src/block-sha1/sha1.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/block-sha1/sha1.h
@@ -0,0 +1,22 @@
+/*
+ * SHA1 routine optimized to do word accesses rather than byte accesses,
+ * and to avoid unnecessary copies into the context array.
+ *
+ * This was initially based on the Mozilla SHA1 implementation, although
+ * none of the original Mozilla code remains.
+ */
+
+typedef struct {
+	unsigned long long size;
+	unsigned int H[5];
+	unsigned int W[16];
+} blk_SHA_CTX;
+
+void git__blk_SHA1_Init(blk_SHA_CTX *ctx);
+void git__blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len);
+void git__blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
+
+#define SHA_CTX		blk_SHA_CTX
+#define SHA1_Init	git__blk_SHA1_Init
+#define SHA1_Update	git__blk_SHA1_Update
+#define SHA1_Final	git__blk_SHA1_Final
diff --git a/libgit2/src/bswap.h b/libgit2/src/bswap.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/bswap.h
@@ -0,0 +1,97 @@
+/*
+ * Let's make sure we always have a sane definition for ntohl()/htonl().
+ * Some libraries define those as a function call, just to perform byte
+ * shifting, bringing significant overhead to what should be a simple
+ * operation.
+ */
+
+#include "common.h"
+
+/*
+ * Default version that the compiler ought to optimize properly with
+ * constant values.
+ */
+GIT_INLINE(uint32_t) default_swab32(uint32_t val)
+{
+	return (((val & 0xff000000) >> 24) |
+		((val & 0x00ff0000) >>  8) |
+		((val & 0x0000ff00) <<  8) |
+		((val & 0x000000ff) << 24));
+}
+
+#undef bswap32
+
+GIT_INLINE(uint16_t) default_swab16(uint16_t val)
+{
+	return (((val & 0xff00) >> 8) |
+		((val & 0x00ff) << 8));
+}
+
+#undef bswap16
+
+#if defined(__GNUC__) && defined(__i386__)
+
+#define bswap32(x) ({ \
+	uint32_t __res; \
+	if (__builtin_constant_p(x)) { \
+		__res = default_swab32(x); \
+	} else { \
+		__asm__("bswap %0" : "=r" (__res) : "0" ((uint32_t)(x))); \
+	} \
+	__res; })
+
+#define bswap16(x) ({ \
+	uint16_t __res; \
+	if (__builtin_constant_p(x)) { \
+		__res = default_swab16(x); \
+	} else { \
+		__asm__("xchgb %b0,%h0" : "=q" (__res) : "0" ((uint16_t)(x))); \
+	} \
+	__res; })
+
+#elif defined(__GNUC__) && defined(__x86_64__)
+
+#define bswap32(x) ({ \
+	uint32_t __res; \
+	if (__builtin_constant_p(x)) { \
+		__res = default_swab32(x); \
+	} else { \
+		__asm__("bswapl %0" : "=r" (__res) : "0" ((uint32_t)(x))); \
+	} \
+	__res; })
+
+#define bswap16(x) ({ \
+	uint16_t __res; \
+	if (__builtin_constant_p(x)) { \
+		__res = default_swab16(x); \
+	} else { \
+		__asm__("xchgb %b0,%h0" : "=Q" (__res) : "0" ((uint16_t)(x))); \
+	} \
+	__res; })
+
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+#include <stdlib.h>
+
+#define bswap32(x) _byteswap_ulong(x)
+#define bswap16(x) _byteswap_ushort(x)
+
+#endif
+
+#ifdef bswap32
+
+#undef ntohl
+#undef htonl
+#define ntohl(x) bswap32(x)
+#define htonl(x) bswap32(x)
+
+#endif
+
+#ifdef bswap16
+
+#undef ntohs
+#undef htons
+#define ntohs(x) bswap16(x)
+#define htons(x) bswap16(x)
+
+#endif
diff --git a/libgit2/src/cc-compat.h b/libgit2/src/cc-compat.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/cc-compat.h
@@ -0,0 +1,73 @@
+/*
+ * cc-compat.h - C compiler compat macros for internal use
+ */
+#ifndef INCLUDE_compat_h__
+#define INCLUDE_compat_h__
+
+/*
+ * See if our compiler is known to support flexible array members.
+ */
+#ifndef GIT_FLEX_ARRAY
+# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#  define GIT_FLEX_ARRAY /* empty */
+# elif defined(__GNUC__)
+#  if (__GNUC__ >= 3)
+#   define GIT_FLEX_ARRAY /* empty */
+#  else
+#   define GIT_FLEX_ARRAY 0 /* older GNU extension */
+#  endif
+# endif
+
+/* Default to safer but a bit wasteful traditional style */
+# ifndef GIT_FLEX_ARRAY
+#  define GIT_FLEX_ARRAY 1
+# endif
+#endif
+
+#ifdef __GNUC__
+# define GIT_TYPEOF(x) (__typeof__(x))
+#else
+# define GIT_TYPEOF(x)
+#endif
+
+#ifdef __cplusplus
+# define GIT_UNUSED(x)
+#else
+# ifdef __GNUC__
+#  define GIT_UNUSED(x) x __attribute__ ((__unused__))
+# else
+#  define GIT_UNUSED(x) x
+# endif
+#endif
+
+#if defined(_MSC_VER)
+#define GIT_UNUSED_ARG(x) ((void)(x)); /* note trailing ; */
+#else
+#define GIT_UNUSED_ARG(x)
+#endif
+
+/*
+ * Does our compiler/platform support the C99 <inttypes.h> and
+ * <stdint.h> header files. (C99 requires that <inttypes.h>
+ * includes <stdint.h>).
+ */
+#if !defined(_MSC_VER)
+# define GIT_HAVE_INTTYPES_H 1
+#endif
+
+/* Define the printf format specifer to use for size_t output */
+#if defined(_MSC_VER) || defined(__MINGW32__)
+# define PRIuZ "Iu"
+#else
+# define PRIuZ "zu"
+#endif
+
+/* Micosoft Visual C/C++ */
+#if defined(_MSC_VER)
+/* disable "deprecated function" warnings */
+# pragma warning ( disable : 4996 )
+/* disable "conditional expression is constant" level 4 warnings */
+# pragma warning ( disable : 4127 )
+#endif
+
+#endif /* INCLUDE_compat_h__ */
diff --git a/libgit2/src/commit.c b/libgit2/src/commit.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/commit.c
@@ -0,0 +1,299 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "git2/common.h"
+#include "git2/object.h"
+#include "git2/repository.h"
+#include "git2/signature.h"
+
+#include "common.h"
+#include "commit.h"
+#include "signature.h"
+
+#define COMMIT_BASIC_PARSE 0x0
+#define COMMIT_FULL_PARSE 0x1
+
+#define COMMIT_PRINT(commit) {\
+	char oid[41]; oid[40] = 0;\
+	git_oid_fmt(oid, &commit->object.id);\
+	printf("Oid: %s | In degree: %d | Time: %u\n", oid, commit->in_degree, commit->commit_time);\
+}
+
+static void clear_parents(git_commit *commit)
+{
+	unsigned int i;
+
+	for (i = 0; i < commit->parent_oids.length; ++i) {
+		git_oid *parent = git_vector_get(&commit->parent_oids, i);
+		free(parent);
+	}
+
+	git_vector_clear(&commit->parent_oids);
+}
+
+void git_commit__free(git_commit *commit)
+{
+	clear_parents(commit);
+	git_vector_free(&commit->parent_oids);
+
+	git_signature_free(commit->author);
+	git_signature_free(commit->committer);
+
+	free(commit->message);
+	free(commit->message_short);
+	free(commit);
+}
+
+const git_oid *git_commit_id(git_commit *c)
+{
+	return git_object_id((git_object *)c);
+}
+
+int git_commit__writeback(git_commit *commit, git_odb_source *src)
+{
+	unsigned int i;
+
+	git__write_oid(src, "tree", &commit->tree_oid);
+
+	for (i = 0; i < commit->parent_oids.length; ++i) {
+		git_oid *parent_oid;
+
+		parent_oid = git_vector_get(&commit->parent_oids, i);
+		git__write_oid(src, "parent", parent_oid);
+	}
+
+	if (commit->author == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	git_signature__write(src, "author", commit->author);
+
+	if (commit->committer == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	git_signature__write(src, "committer", commit->committer);
+
+	if (commit->message != NULL) {
+		git__source_write(src, "\n", 1);
+		git__source_write(src, commit->message, strlen(commit->message));
+	}
+
+	return GIT_SUCCESS;
+}
+
+int commit_parse_buffer(git_commit *commit, void *data, size_t len)
+{
+	char *buffer = (char *)data;
+	const char *buffer_end = (char *)data + len;
+
+	git_oid parent_oid;
+	int error;
+
+	/* first parse; the vector hasn't been initialized yet */
+	if (commit->parent_oids.contents == NULL) {
+		git_vector_init(&commit->parent_oids, 4, NULL);
+	}
+
+	clear_parents(commit);
+
+	if ((error = git__parse_oid(&commit->tree_oid, &buffer, buffer_end, "tree ")) < GIT_SUCCESS)
+		return error;
+
+	/*
+	 * TODO: commit grafts!
+	 */
+
+	while (git__parse_oid(&parent_oid, &buffer, buffer_end, "parent ") == GIT_SUCCESS) {
+		git_oid *new_oid;
+
+		new_oid = git__malloc(sizeof(git_oid));
+		git_oid_cpy(new_oid, &parent_oid);
+
+		if (git_vector_insert(&commit->parent_oids, new_oid) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+	}
+
+	if (commit->author)
+		git_signature_free(commit->author);
+
+	commit->author = git__malloc(sizeof(git_signature));
+	if ((error = git_signature__parse(commit->author, &buffer, buffer_end, "author ")) < GIT_SUCCESS)
+		return error;
+
+	/* Always parse the committer; we need the commit time */
+	if (commit->committer)
+		git_signature_free(commit->committer);
+
+	commit->committer = git__malloc(sizeof(git_signature));
+	if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ")) < GIT_SUCCESS)
+		return error;
+
+	/* parse commit message */
+	while (buffer <= buffer_end && *buffer == '\n')
+		buffer++;
+
+	if (buffer < buffer_end) {
+		const char *line_end;
+		size_t message_len = buffer_end - buffer;
+
+		/* Long message */
+		message_len = buffer_end - buffer;
+		commit->message = git__malloc(message_len + 1);
+		memcpy(commit->message, buffer, message_len);
+		commit->message[message_len] = 0;
+
+		/* Short message */
+		if((line_end = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
+			line_end = buffer_end;
+		message_len = line_end - buffer;
+
+		commit->message_short = git__malloc(message_len + 1);
+		memcpy(commit->message_short, buffer, message_len);
+		commit->message_short[message_len] = 0;
+	}
+
+	return GIT_SUCCESS;
+}
+
+int git_commit__parse(git_commit *commit)
+{
+	assert(commit && commit->object.source.open);
+	return commit_parse_buffer(commit,
+			commit->object.source.raw.data, commit->object.source.raw.len);
+}
+
+#define GIT_COMMIT_GETTER(_rvalue, _name, _return) \
+	_rvalue git_commit_##_name(git_commit *commit) \
+	{\
+		assert(commit); \
+		return _return; \
+	}
+
+GIT_COMMIT_GETTER(const git_signature *, author, commit->author)
+GIT_COMMIT_GETTER(const git_signature *, committer, commit->committer)
+GIT_COMMIT_GETTER(const char *, message, commit->message)
+GIT_COMMIT_GETTER(const char *, message_short, commit->message_short)
+GIT_COMMIT_GETTER(time_t, time, commit->committer->when.time)
+GIT_COMMIT_GETTER(int, time_offset, commit->committer->when.offset)
+GIT_COMMIT_GETTER(unsigned int, parentcount, commit->parent_oids.length)
+
+
+int git_commit_tree(git_tree **tree_out, git_commit *commit)
+{
+	assert(commit);
+	return git_tree_lookup(tree_out, commit->object.repo, &commit->tree_oid);
+}
+
+int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
+{
+	git_oid *parent_oid;
+	assert(commit);
+
+	parent_oid = git_vector_get(&commit->parent_oids, n);
+	if (parent_oid == NULL)
+		return GIT_ENOTFOUND;
+
+	return git_commit_lookup(parent, commit->object.repo, parent_oid);
+}
+
+
+
+int git_commit_set_tree(git_commit *commit, git_tree *tree)
+{
+	const git_oid *oid;
+
+	assert(commit && tree);
+
+	if ((oid = git_object_id((git_object *)tree)) == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	commit->object.modified = 1;
+	git_oid_cpy(&commit->tree_oid, oid);
+	return GIT_SUCCESS;
+}
+
+int git_commit_add_parent(git_commit *commit, git_commit *new_parent)
+{
+	const git_oid *parent_oid;
+	git_oid *new_oid;
+	assert(commit && new_parent);
+
+	if ((parent_oid = git_object_id((git_object *)new_parent)) == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	new_oid = git__malloc(sizeof(git_oid));
+	if (new_oid == NULL)
+		return GIT_ENOMEM;
+
+	commit->object.modified = 1;
+	git_oid_cpy(new_oid, parent_oid);
+	return git_vector_insert(&commit->parent_oids, new_oid);
+}
+
+void git_commit_set_author(git_commit *commit, const git_signature *author_sig)
+{
+	assert(commit && author_sig);
+	commit->object.modified = 1;
+
+	git_signature_free(commit->author);
+	commit->author = git_signature_dup(author_sig);
+}
+
+void git_commit_set_committer(git_commit *commit, const git_signature *committer_sig)
+{
+	assert(commit && committer_sig);
+	commit->object.modified = 1;
+
+	git_signature_free(commit->committer);
+	commit->committer = git_signature_dup(committer_sig);
+}
+
+void git_commit_set_message(git_commit *commit, const char *message)
+{
+	const char *line_end;
+	size_t message_len;
+
+	commit->object.modified = 1;
+
+	if (commit->message)
+		free(commit->message);
+
+	if (commit->message_short)
+		free(commit->message_short);
+
+	commit->message = git__strdup(message);
+
+	/* Short message */
+	if((line_end = strchr(message, '\n')) == NULL) {
+		commit->message_short = git__strdup(message);
+		return;
+	}
+
+	message_len = line_end - message;
+
+	commit->message_short = git__malloc(message_len + 1);
+	memcpy(commit->message_short, message, message_len);
+	commit->message_short[message_len] = 0;
+}
+
diff --git a/libgit2/src/commit.h b/libgit2/src/commit.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/commit.h
@@ -0,0 +1,29 @@
+#ifndef INCLUDE_commit_h__
+#define INCLUDE_commit_h__
+
+#include "git2/commit.h"
+#include "tree.h"
+#include "repository.h"
+#include "vector.h"
+
+#include <time.h>
+
+struct git_commit {
+	git_object object;
+
+	git_vector parent_oids;
+	git_oid tree_oid;
+
+	git_signature *author;
+	git_signature *committer;
+
+	char *message;
+	char *message_short;
+};
+
+void git_commit__free(git_commit *c);
+int git_commit__parse(git_commit *commit);
+
+int git_commit__writeback(git_commit *commit, git_odb_source *src);
+
+#endif
diff --git a/libgit2/src/common.h b/libgit2/src/common.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/common.h
@@ -0,0 +1,56 @@
+#ifndef INCLUDE_common_h__
+#define INCLUDE_common_h__
+
+/** Force 64 bit off_t size on POSIX. */
+#define _FILE_OFFSET_BITS 64
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define GIT_WIN32 1
+#endif
+
+#include "git2/thread-utils.h"
+#include "cc-compat.h"
+
+#ifdef GIT_HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef GIT_WIN32
+
+# include <io.h>
+# include <direct.h>
+# include <windows.h>
+# include "msvc-compat.h"
+# include "mingw-compat.h"
+# include "win32/pthread.h"
+
+# define snprintf _snprintf
+
+typedef SSIZE_T ssize_t;
+
+#else
+
+# include <unistd.h>
+# include <arpa/inet.h>
+# include <pthread.h>
+
+#endif
+
+#include "git2/common.h"
+#include "git2/types.h"
+#include "util.h"
+#include "thread-utils.h"
+#include "bswap.h"
+
+#define GIT_PATH_MAX 4096
+
+#endif /* INCLUDE_common_h__ */
diff --git a/libgit2/src/delta-apply.c b/libgit2/src/delta-apply.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/delta-apply.c
@@ -0,0 +1,109 @@
+#include "common.h"
+#include "git2/odb.h"
+#include "delta-apply.h"
+
+/*
+ * This file was heavily cribbed from BinaryDelta.java in JGit, which
+ * itself was heavily cribbed from <code>patch-delta.c</code> in the
+ * GIT project.   The original delta patching code was written by
+ * Nicolas Pitre <nico@cam.org>.
+ */
+
+static int hdr_sz(
+	size_t *size,
+	const unsigned char **delta,
+	const unsigned char *end)
+{
+	const unsigned char *d = *delta;
+	size_t r = 0;
+	unsigned int c, shift = 0;
+
+	do {
+		if (d == end)
+			return -1;
+		c = *d++;
+		r |= (c & 0x7f) << shift;
+		shift += 7;
+	} while (c & 0x80);
+	*delta = d;
+	*size = r;
+	return 0;
+}
+
+int git__delta_apply(
+	git_rawobj *out,
+	const unsigned char *base,
+	size_t base_len,
+	const unsigned char *delta,
+	size_t delta_len)
+{
+	const unsigned char *delta_end = delta + delta_len;
+	size_t base_sz, res_sz;
+	unsigned char *res_dp;
+
+	/* Check that the base size matches the data we were given;
+	 * if not we would underflow while accessing data from the
+	 * base object, resulting in data corruption or segfault.
+	 */
+	if ((hdr_sz(&base_sz, &delta, delta_end) < 0) || (base_sz != base_len))
+		return GIT_ERROR;
+
+	if (hdr_sz(&res_sz, &delta, delta_end) < 0)
+		return GIT_ERROR;
+
+	if ((res_dp = git__malloc(res_sz + 1)) == NULL)
+		return GIT_ERROR;
+	res_dp[res_sz] = '\0';
+	out->data = res_dp;
+	out->len = res_sz;
+
+	while (delta < delta_end) {
+		unsigned char cmd = *delta++;
+		if (cmd & 0x80) {
+			/* cmd is a copy instruction; copy from the base.
+			 */
+			size_t off = 0, len = 0;
+
+			if (cmd & 0x01) off  = *delta++;
+			if (cmd & 0x02) off |= *delta++ <<  8;
+			if (cmd & 0x04) off |= *delta++ << 16;
+			if (cmd & 0x08) off |= *delta++ << 24;
+
+			if (cmd & 0x10) len  = *delta++;
+			if (cmd & 0x20) len |= *delta++ <<  8;
+			if (cmd & 0x40) len |= *delta++ << 16;
+			if (!len)       len  = 0x10000;
+
+			if (base_len < off + len || res_sz < len)
+				goto fail;
+			memcpy(res_dp, base + off, len);
+			res_dp += len;
+			res_sz -= len;
+
+		} else if (cmd) {
+			/* cmd is a literal insert instruction; copy from
+			 * the delta stream itself.
+			 */
+			if (delta_end - delta < cmd || res_sz < cmd)
+				goto fail;
+			memcpy(res_dp, delta, cmd);
+			delta  += cmd;
+			res_dp += cmd;
+			res_sz -= cmd;
+
+		} else {
+			/* cmd == 0 is reserved for future encodings.
+			 */
+			goto fail;
+		}
+	}
+
+	if (delta != delta_end || res_sz)
+		goto fail;
+	return GIT_SUCCESS;
+
+fail:
+	free(out->data);
+	out->data = NULL;
+	return GIT_ERROR;
+}
diff --git a/libgit2/src/delta-apply.h b/libgit2/src/delta-apply.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/delta-apply.h
@@ -0,0 +1,25 @@
+#ifndef INCLUDE_delta_apply_h__
+#define INCLUDE_delta_apply_h__
+
+/**
+ * Apply a git binary delta to recover the original content.
+ *
+ * @param out the output buffer to receive the original data.
+ *		Only out->data and out->len are populated, as this is
+ *		the only information available in the delta.
+ * @param base the base to copy from during copy instructions.
+ * @param base_len number of bytes available at base.
+ * @param delta the delta to execute copy/insert instructions from.
+ * @param delta_len total number of bytes in the delta.
+ * @return
+ * - GIT_SUCCESS on a successful delta unpack.
+ * - GIT_ERROR if the delta is corrupt or doesn't match the base.
+ */
+extern int git__delta_apply(
+	git_rawobj *out,
+	const unsigned char *base,
+	size_t base_len,
+	const unsigned char *delta,
+	size_t delta_len);
+
+#endif
diff --git a/libgit2/src/dir.h b/libgit2/src/dir.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/dir.h
@@ -0,0 +1,41 @@
+#ifndef INCLUDE_dir_h__
+#define INCLUDE_dir_h__
+
+#include "common.h"
+
+#ifndef GIT_WIN32
+# include <dirent.h>
+#endif
+
+#ifdef GIT_WIN32
+
+struct git__dirent {
+	int  d_ino;
+	char d_name[261];
+};
+
+typedef struct {
+	HANDLE h;
+	WIN32_FIND_DATA f;
+	struct git__dirent entry;
+	char *dir;
+	int first;
+} git__DIR;
+
+extern git__DIR *git__opendir(const char *);
+extern struct git__dirent *git__readdir(git__DIR *);
+extern void git__rewinddir(git__DIR *);
+extern int git__closedir(git__DIR *);
+
+# ifndef GIT__WIN32_NO_WRAP_DIR
+#  define dirent git__dirent
+#  define DIR git__DIR
+#  define opendir   git__opendir
+#  define readdir   git__readdir
+#  define rewinddir git__rewinddir
+#  define closedir  git__closedir
+# endif
+
+#endif
+
+#endif /* INCLUDE_dir_h__ */
diff --git a/libgit2/src/errors.c b/libgit2/src/errors.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/errors.c
@@ -0,0 +1,44 @@
+#include "common.h"
+#include "thread-utils.h" /* for GIT_TLS */
+
+static struct {
+	int num;
+	const char *str;
+} error_codes[] = {
+	{GIT_ERROR, "Unspecified error"},
+	{GIT_ENOTOID, "Input was not a properly formatted Git object id."},
+	{GIT_ENOTFOUND, "Object does not exist in the scope searched."},
+	{GIT_ENOMEM, "Not enough space available."},
+	{GIT_EOSERR, "Consult the OS error information."},
+	{GIT_EOBJTYPE, "The specified object is of invalid type"},
+	{GIT_EOBJCORRUPTED, "The specified object has its data corrupted"},
+	{GIT_ENOTAREPO, "The specified repository is invalid"},
+	{GIT_EINVALIDTYPE, "The object type is invalid or doesn't match"},
+	{GIT_EMISSINGOBJDATA, "The object cannot be written that because it's missing internal data"},
+	{GIT_EPACKCORRUPTED, "The packfile for the ODB is corrupted"},
+	{GIT_EFLOCKFAIL, "Failed to adquire or release a file lock"},
+	{GIT_EZLIB, "The Z library failed to inflate/deflate an object's data"},
+	{GIT_EBUSY, "The queried object is currently busy"},
+	{GIT_EINVALIDPATH, "The path is invalid"},
+	{GIT_EBAREINDEX, "The index file is not backed up by an existing repository"},
+	{GIT_EINVALIDREFNAME, "The name of the reference is not valid"},
+	{GIT_EREFCORRUPTED, "The specified reference has its data corrupted"},
+	{GIT_ETOONESTEDSYMREF, "The specified symbolic reference is too deeply nested"},
+	{GIT_EPACKEDREFSCORRUPTED, "The pack-refs file is either corrupted of its format is not currently supported"},
+	{GIT_EINVALIDPATH, "The path is invalid" },
+	{GIT_EREVWALKOVER, "The revision walker is empty; there are no more commits left to iterate"},
+	{GIT_EINVALIDREFSTATE, "The state of the reference is not valid"}
+};
+
+const char *git_strerror(int num)
+{
+	size_t i;
+
+	if (num == GIT_EOSERR)
+		return strerror(errno);
+	for (i = 0; i < ARRAY_SIZE(error_codes); i++)
+		if (num == error_codes[i].num)
+			return error_codes[i].str;
+
+	return "Unknown error";
+}
diff --git a/libgit2/src/filebuf.c b/libgit2/src/filebuf.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/filebuf.c
@@ -0,0 +1,291 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <stdarg.h>
+
+#include "common.h"
+#include "filebuf.h"
+#include "fileops.h"
+
+static const size_t WRITE_BUFFER_SIZE = (4096 * 2);
+
+static int lock_file(git_filebuf *file, int flags)
+{
+	if (gitfo_exists(file->path_lock) == 0) {
+		if (flags & GIT_FILEBUF_FORCE)
+			gitfo_unlink(file->path_lock);
+		else
+			return GIT_EOSERR;
+	}
+
+	/* create path to the file buffer is required */
+	if (flags & GIT_FILEBUF_FORCE) {
+		file->fd = gitfo_creat_force(file->path_lock, 0644);
+	} else {
+		file->fd = gitfo_creat(file->path_lock, 0644);
+	}
+
+	if (file->fd < 0)
+		return GIT_EOSERR;
+
+	/* TODO: do a flock() in the descriptor file_lock */
+
+	if ((flags & GIT_FILEBUF_APPEND) && gitfo_exists(file->path_original) == 0) {
+		git_file source;
+		char buffer[2048];
+		size_t read_bytes;
+
+		source = gitfo_open(file->path_original, O_RDONLY);
+		if (source < 0)
+			return GIT_EOSERR;
+
+		while ((read_bytes = gitfo_read(source, buffer, 2048)) > 0) {
+			gitfo_write(file->fd, buffer, read_bytes);
+			if (file->digest)
+				git_hash_update(file->digest, buffer, read_bytes);
+		}
+
+		gitfo_close(source);
+	}
+
+	return GIT_SUCCESS;
+}
+
+void git_filebuf_cleanup(git_filebuf *file)
+{
+	if (file->fd >= 0)
+		gitfo_close(file->fd);
+
+	if (gitfo_exists(file->path_lock) == GIT_SUCCESS)
+		gitfo_unlink(file->path_lock);
+
+	if (file->digest)
+		git_hash_free_ctx(file->digest);
+
+	free(file->buffer);
+
+#ifdef GIT_FILEBUF_THREADS
+	free(file->buffer_back);
+#endif
+
+	free(file->path_original);
+	free(file->path_lock);
+}
+
+static int flush_buffer(git_filebuf *file)
+{
+	int result = GIT_SUCCESS;
+
+	if (file->buf_pos > 0) {
+		result = gitfo_write(file->fd, file->buffer, file->buf_pos);
+		if (file->digest)
+			git_hash_update(file->digest, file->buffer, file->buf_pos);
+
+		file->buf_pos = 0;
+	}
+
+	return result;
+}
+
+int git_filebuf_open(git_filebuf *file, const char *path, int flags)
+{
+	int error;
+	size_t path_len;
+
+	if (file == NULL || path == NULL)
+		return GIT_ERROR;
+
+	memset(file, 0x0, sizeof(git_filebuf));
+
+	file->buf_size = WRITE_BUFFER_SIZE;
+	file->buf_pos = 0;
+	file->fd = -1;
+
+	path_len = strlen(path);
+
+	file->path_original = git__strdup(path);
+	if (file->path_original == NULL) {
+		error = GIT_ENOMEM;
+		goto cleanup;
+	}
+
+	file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH);
+	if (file->path_lock == NULL) {
+		error = GIT_ENOMEM;
+		goto cleanup;
+	}
+
+	memcpy(file->path_lock, file->path_original, path_len);
+	memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH);
+
+	file->buffer = git__malloc(file->buf_size);
+	if (file->buffer == NULL){
+		error = GIT_ENOMEM;
+		goto cleanup;
+	}
+
+#ifdef GIT_FILEBUF_THREADS
+	file->buffer_back = git__malloc(file->buf_size);
+	if (file->buffer_back == NULL){
+		error = GIT_ENOMEM;
+		goto cleanup;
+	}
+#endif
+
+	if (flags & GIT_FILEBUF_HASH_CONTENTS) {
+		if ((file->digest = git_hash_new_ctx()) == NULL) {
+			error = GIT_ENOMEM;
+			goto cleanup;
+		}
+	}
+
+	if ((error = lock_file(file, flags)) < GIT_SUCCESS)
+		goto cleanup;
+
+	return GIT_SUCCESS;
+
+cleanup:
+	git_filebuf_cleanup(file);
+	return error;
+}
+
+int git_filebuf_hash(git_oid *oid, git_filebuf *file)
+{
+	int error;
+
+	if (file->digest == NULL)
+		return GIT_ERROR;
+
+	if ((error = flush_buffer(file)) < GIT_SUCCESS)
+		return error;
+
+	git_hash_final(oid, file->digest);
+	git_hash_free_ctx(file->digest);
+	file->digest = NULL;
+
+	return GIT_SUCCESS;
+}
+
+int git_filebuf_commit(git_filebuf *file)
+{
+	int error;
+
+	if ((error = flush_buffer(file)) < GIT_SUCCESS)
+		goto cleanup;
+
+	gitfo_close(file->fd);
+	file->fd = -1;
+
+	error = gitfo_mv(file->path_lock, file->path_original);
+
+cleanup:
+	git_filebuf_cleanup(file);
+	return error;
+}
+
+GIT_INLINE(void) add_to_cache(git_filebuf *file, void *buf, size_t len)
+{
+	memcpy(file->buffer + file->buf_pos, buf, len);
+	file->buf_pos += len;
+}
+
+int git_filebuf_write(git_filebuf *file, void *buff, size_t len)
+{
+	int error;
+	unsigned char *buf = buff;
+
+	for (;;) {
+		size_t space_left = file->buf_size - file->buf_pos;
+
+		/* cache if it's small */
+		if (space_left > len) {
+			add_to_cache(file, buf, len);
+			return GIT_SUCCESS;
+		}
+
+		/* flush the cache if it doesn't fit */
+		if (file->buf_pos > 0) {
+			add_to_cache(file, buf, space_left);
+
+			if ((error = flush_buffer(file)) < GIT_SUCCESS)
+				return error;
+
+			len -= space_left;
+			buf += space_left;
+		}
+
+		/* write too-large chunks immediately */
+		if (len > file->buf_size) {
+			error = gitfo_write(file->fd, buf, len);
+			if (file->digest)
+				git_hash_update(file->digest, buf, len);
+		}
+	}
+}
+
+int git_filebuf_reserve(git_filebuf *file, void **buffer, size_t len)
+{
+	int error;
+	size_t space_left = file->buf_size - file->buf_pos;
+
+	*buffer = NULL;
+
+	if (len > file->buf_size)
+		return GIT_ENOMEM;
+
+	if (space_left <= len) {
+		if ((error = flush_buffer(file)) < GIT_SUCCESS)
+			return error;
+	}
+
+	*buffer = (file->buffer + file->buf_pos);
+	file->buf_pos += len;
+
+	return GIT_SUCCESS;
+}
+
+int git_filebuf_printf(git_filebuf *file, const char *format, ...)
+{
+	va_list arglist;
+	size_t space_left = file->buf_size - file->buf_pos;
+	int len, error;
+
+	va_start(arglist, format);
+
+	len = vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
+
+	if (len < 0 || (size_t)len >= space_left) {
+		if ((error = flush_buffer(file)) < GIT_SUCCESS)
+			return error;
+
+		len = vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
+		if (len < 0 || (size_t)len > file->buf_size)
+			return GIT_ENOMEM;
+	}
+
+	file->buf_pos += len;
+	return GIT_SUCCESS;
+
+}
+
diff --git a/libgit2/src/filebuf.h b/libgit2/src/filebuf.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/filebuf.h
@@ -0,0 +1,44 @@
+#ifndef INCLUDE_filebuf_h__
+#define INCLUDE_filebuf_h__
+
+#include "fileops.h"
+#include "hash.h"
+
+#ifdef GIT_THREADS
+#	define GIT_FILEBUF_THREADS
+#endif
+
+#define GIT_FILEBUF_HASH_CONTENTS 0x1
+#define GIT_FILEBUF_APPEND 0x2
+#define GIT_FILEBUF_FORCE 0x4
+
+#define GIT_FILELOCK_EXTENSION ".lock\0"
+#define GIT_FILELOCK_EXTLENGTH 6
+
+struct git_filebuf {
+	char *path_original;
+	char *path_lock;
+
+	git_hash_ctx *digest;
+
+	unsigned char *buffer;
+#ifdef GIT_FILEBUF_THREADS
+	unsigned char *buffer_back;
+#endif
+
+	size_t buf_size, buf_pos;
+	git_file fd;
+};
+
+typedef struct git_filebuf git_filebuf;
+
+int git_filebuf_write(git_filebuf *lock, void *buff, size_t len);
+int git_filebuf_reserve(git_filebuf *file, void **buff, size_t len);
+int git_filebuf_printf(git_filebuf *file, const char *format, ...);
+
+int git_filebuf_open(git_filebuf *lock, const char *path, int flags);
+int git_filebuf_commit(git_filebuf *lock);
+void git_filebuf_cleanup(git_filebuf *lock);
+int git_filebuf_hash(git_oid *oid, git_filebuf *file);
+
+#endif
diff --git a/libgit2/src/fileops.c b/libgit2/src/fileops.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/fileops.c
@@ -0,0 +1,553 @@
+#include "common.h"
+#include "fileops.h"
+#include <ctype.h>
+
+static int force_path(const char *to)
+{
+	const int mode = 0755; /* or 0777 ? */
+	int error = GIT_SUCCESS;
+	char target_folder_path[GIT_PATH_MAX];
+
+	error = git__dirname_r(target_folder_path, sizeof(target_folder_path), to);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	/* Does the containing folder exist? */
+	if (gitfo_isdir(target_folder_path)) {
+		git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */
+
+		/* Let's create the tree structure */
+		error = gitfo_mkdir_recurs(target_folder_path, mode);
+		if (error < GIT_SUCCESS)
+			return error;
+	}
+
+	return GIT_SUCCESS;
+}
+
+int gitfo_open(const char *path, int flags)
+{
+	int fd = open(path, flags | O_BINARY);
+	return fd >= 0 ? fd : GIT_EOSERR;
+}
+
+int gitfo_creat(const char *path, int mode)
+{
+	int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
+	return fd >= 0 ? fd : GIT_EOSERR;
+}
+
+int gitfo_creat_force(const char *path, int mode)
+{
+	if (force_path(path) < GIT_SUCCESS)
+		return GIT_EOSERR;
+
+	return gitfo_creat(path, mode);
+}
+
+int gitfo_read(git_file fd, void *buf, size_t cnt)
+{
+	char *b = buf;
+	while (cnt) {
+		ssize_t r = read(fd, b, cnt);
+		if (r < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				continue;
+			return GIT_EOSERR;
+		}
+		if (!r) {
+			errno = EPIPE;
+			return GIT_EOSERR;
+		}
+		cnt -= r;
+		b += r;
+	}
+	return GIT_SUCCESS;
+}
+
+int gitfo_write(git_file fd, void *buf, size_t cnt)
+{
+	char *b = buf;
+	while (cnt) {
+		ssize_t r = write(fd, b, cnt);
+		if (r < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				continue;
+			return GIT_EOSERR;
+		}
+		if (!r) {
+			errno = EPIPE;
+			return GIT_EOSERR;
+		}
+		cnt -= r;
+		b += r;
+	}
+	return GIT_SUCCESS;
+}
+
+int gitfo_isdir(const char *path)
+{
+	struct stat st;
+	int len, stat_error;
+
+	if (!path)
+		return GIT_ENOTFOUND;
+
+	len = strlen(path);
+
+	/* win32: stat path for folders cannot end in a slash */
+	if (path[len - 1] == '/') {
+		char *path_fixed = NULL;
+		path_fixed = git__strdup(path);
+		path_fixed[len - 1] = 0;
+		stat_error = gitfo_stat(path_fixed, &st);
+		free(path_fixed);
+	} else {
+		stat_error = gitfo_stat(path, &st);
+	}
+
+	if (stat_error < GIT_SUCCESS)
+		return GIT_ENOTFOUND;
+
+	if (!S_ISDIR(st.st_mode))
+		return GIT_ENOTFOUND;
+
+	return GIT_SUCCESS;
+}
+
+int gitfo_exists(const char *path)
+{
+	return access(path, F_OK);
+}
+
+git_off_t gitfo_size(git_file fd)
+{
+	struct stat sb;
+	if (gitfo_fstat(fd, &sb))
+		return GIT_EOSERR;
+	return sb.st_size;
+}
+
+int gitfo_read_file(gitfo_buf *obj, const char *path)
+{
+	git_file fd;
+	size_t len;
+	git_off_t size;
+	unsigned char *buff;
+
+	assert(obj && path && *path);
+
+	if ((fd = gitfo_open(path, O_RDONLY)) < 0)
+		return GIT_ERROR;
+
+	if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) {
+		gitfo_close(fd);
+		return GIT_ERROR;
+	}
+	len = (size_t) size;
+
+	if ((buff = git__malloc(len + 1)) == NULL) {
+		gitfo_close(fd);
+		return GIT_ERROR;
+	}
+
+	if (gitfo_read(fd, buff, len) < 0) {
+		gitfo_close(fd);
+		free(buff);
+		return GIT_ERROR;
+	}
+	buff[len] = '\0';
+
+	gitfo_close(fd);
+
+	obj->data = buff;
+	obj->len  = len;
+
+	return GIT_SUCCESS;
+}
+
+void gitfo_free_buf(gitfo_buf *obj)
+{
+	assert(obj);
+	free(obj->data);
+	obj->data = NULL;
+}
+
+int gitfo_mv(const char *from, const char *to)
+{
+#ifdef GIT_WIN32
+	/*
+	 * Win32 POSIX compilance my ass. If the destination
+	 * file exists, the `rename` call fails. This is as
+	 * close as it gets with the Win32 API.
+	 */
+	return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) ? GIT_SUCCESS : GIT_EOSERR;
+#else
+	/* Don't even try this on Win32 */
+	if (!link(from, to)) {
+		gitfo_unlink(from);
+		return GIT_SUCCESS;
+	}
+
+	if (!rename(from, to))
+		return GIT_SUCCESS;
+
+	return GIT_EOSERR;
+#endif
+}
+
+int gitfo_mv_force(const char *from, const char *to)
+{
+	if (force_path(to) < GIT_SUCCESS)
+		return GIT_EOSERR;
+
+	return gitfo_mv(from, to);
+}
+
+int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
+{
+	if (git__mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin) < GIT_SUCCESS)
+		return GIT_EOSERR;
+	return GIT_SUCCESS;
+}
+
+void gitfo_free_map(git_map *out)
+{
+	git__munmap(out);
+}
+
+/* cached diskio */
+struct gitfo_cache {
+	git_file fd;
+	size_t cache_size, pos;
+	unsigned char *cache;
+};
+
+gitfo_cache *gitfo_enable_caching(git_file fd, size_t cache_size)
+{
+	gitfo_cache *ioc;
+
+	ioc = git__malloc(sizeof(*ioc));
+	if (!ioc)
+		return NULL;
+
+	ioc->fd = fd;
+	ioc->pos = 0;
+	ioc->cache_size = cache_size;
+	ioc->cache = git__malloc(cache_size);
+	if (!ioc->cache) {
+		free(ioc);
+		return NULL;
+	}
+
+	return ioc;
+}
+
+GIT_INLINE(void) gitfo_add_to_cache(gitfo_cache *ioc, void *buf, size_t len)
+{
+	memcpy(ioc->cache + ioc->pos, buf, len);
+	ioc->pos += len;
+}
+
+int gitfo_flush_cached(gitfo_cache *ioc)
+{
+	int result = GIT_SUCCESS;
+
+	if (ioc->pos) {
+		result = gitfo_write(ioc->fd, ioc->cache, ioc->pos);
+		ioc->pos = 0;
+	}
+
+	return result;
+}
+
+int gitfo_write_cached(gitfo_cache *ioc, void *buff, size_t len)
+{
+	unsigned char *buf = buff;
+
+	for (;;) {
+		size_t space_left = ioc->cache_size - ioc->pos;
+		/* cache if it's small */
+		if (space_left > len) {
+			gitfo_add_to_cache(ioc, buf, len);
+			return GIT_SUCCESS;
+		}
+
+		/* flush the cache if it doesn't fit */
+		if (ioc->pos) {
+			int rc;
+			gitfo_add_to_cache(ioc, buf, space_left);
+			rc = gitfo_flush_cached(ioc);
+			if (rc < 0)
+				return rc;
+
+			len -= space_left;
+			buf += space_left;
+		}
+
+		/* write too-large chunks immediately */
+		if (len > ioc->cache_size)
+			return gitfo_write(ioc->fd, buf, len);
+	}
+}
+
+int gitfo_close_cached(gitfo_cache *ioc)
+{
+	git_file fd;
+
+	if (gitfo_flush_cached(ioc) < GIT_SUCCESS)
+		return GIT_ERROR;
+
+	fd = ioc->fd;
+	free(ioc->cache);
+	free(ioc);
+
+	return gitfo_close(fd);
+}
+
+int gitfo_dirent(
+	char *path,
+	size_t path_sz,
+	int (*fn)(void *, char *),
+	void *arg)
+{
+	size_t wd_len = strlen(path);
+	DIR *dir;
+	struct dirent *de;
+
+	if (!wd_len || path_sz < wd_len + 2)
+		return GIT_ERROR;
+
+	while (path[wd_len - 1] == '/')
+		wd_len--;
+	path[wd_len++] = '/';
+	path[wd_len] = '\0';
+
+	dir = opendir(path);
+	if (!dir)
+		return GIT_EOSERR;
+
+	while ((de = readdir(dir)) != NULL) {
+		size_t de_len;
+		int result;
+
+		/* always skip '.' and '..' */
+		if (de->d_name[0] == '.') {
+			if (de->d_name[1] == '\0')
+				continue;
+			if (de->d_name[1] == '.' && de->d_name[2] == '\0')
+				continue;
+		}
+
+		de_len = strlen(de->d_name);
+		if (path_sz < wd_len + de_len + 1) {
+			closedir(dir);
+			return GIT_ERROR;
+		}
+
+		strcpy(path + wd_len, de->d_name);
+		result = fn(arg, path);
+		if (result < GIT_SUCCESS) {
+			closedir(dir);
+			return result;
+		}
+		if (result > 0) {
+			closedir(dir);
+			return result;
+		}
+	}
+
+	closedir(dir);
+	return GIT_SUCCESS;
+}
+
+#ifdef GIT_WIN32
+
+static int is_windows_rooted_path(const char *path)
+{
+	/* Does the root of the path look like a windows drive ? */
+	if (isalpha(path[0]) && (path[1] == ':'))
+		return GIT_SUCCESS;
+
+	return GIT_ERROR;
+}
+
+#endif
+
+int gitfo_mkdir_recurs(const char *path, int mode)
+{
+	int error;
+	char *pp, *sp;
+    char *path_copy = git__strdup(path);
+
+	if (path_copy == NULL)
+		return GIT_ENOMEM;
+
+	error = GIT_SUCCESS;
+	pp = path_copy;
+
+#ifdef GIT_WIN32
+
+	if (!is_windows_rooted_path(pp))
+		pp += 2; /* Skip the drive name (eg. C: or D:) */
+
+#endif
+
+    while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != 0) {
+		if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) {
+			*sp = 0;
+			error = gitfo_mkdir(path_copy, mode);
+
+			/* Do not choke while trying to recreate an existing directory */
+			if (errno == EEXIST)
+				error = GIT_SUCCESS;
+
+			*sp = '/';
+		}
+
+		pp = sp + 1;
+	}
+
+	if (*(pp - 1) != '/' && error == GIT_SUCCESS)
+		error = gitfo_mkdir(path, mode);
+
+	free(path_copy);
+	return error;
+}
+
+static int retrieve_previous_path_component_start(const char *path)
+{
+	int offset, len, start = 0;
+	
+	len = strlen(path);
+	offset = len - 1;
+
+	/* Skip leading slash */
+	if (path[start] == '/')
+		start++;
+
+	/* Skip trailing slash */
+	if (path[offset] == '/')
+		offset--;
+
+	if (offset < 0)
+		return GIT_ERROR;
+
+	while (offset > start && path[offset-1] != '/') {
+		offset--;
+	}
+
+	return offset;
+}
+
+int gitfo_prettify_dir_path(char *buffer_out, const char *path)
+{
+	int len = 0, segment_len, only_dots;
+	char *current;
+	const char *buffer_out_start, *buffer_end;
+
+	buffer_out_start = buffer_out;
+	current = (char *)path;
+	buffer_end = path + strlen(path);
+
+	while (current < buffer_end) {
+		/* Prevent multiple slashes from being added to the output */
+		if (*current == '/' && len > 0 && buffer_out_start[len - 1] == '/') {
+			current++;
+			continue;
+		}
+		
+		only_dots = 1;
+		segment_len = 0;
+
+		/* Copy path segment to the output */
+		while (current < buffer_end && *current !='/')
+		{
+			only_dots &= (*current == '.');
+			*buffer_out++ = *current++;
+			segment_len++;
+			len++;
+		}
+
+		/* Skip current directory */
+		if (only_dots && segment_len == 1)
+		{
+			current++;
+			buffer_out -= segment_len;
+			len -= segment_len;
+			continue;
+		}
+
+		/* Handle the double-dot upward directory navigation */
+		if (only_dots && segment_len == 2)
+		{
+			current++;
+			buffer_out -= segment_len;
+
+			*buffer_out ='\0';
+			len = retrieve_previous_path_component_start(buffer_out_start);
+			if (len < GIT_SUCCESS)
+				return GIT_EINVALIDPATH;
+
+			buffer_out = (char *)buffer_out_start + len;
+			continue;
+		}
+
+		/* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */
+		if (only_dots &&segment_len > 0)
+			return GIT_EINVALIDPATH;
+
+		*buffer_out++ = '/';
+		len++;
+	}
+
+	*buffer_out = '\0';
+
+	return GIT_SUCCESS;
+}
+
+int gitfo_prettify_file_path(char *buffer_out, const char *path)
+{
+	int error, path_len, i;
+	const char* pattern = "/..";
+
+	path_len = strlen(path);
+
+	/* Let's make sure the filename doesn't end with "/", "/." or "/.." */
+	for (i = 1; path_len > i && i < 4; i++) {
+		if (!strncmp(path + path_len - i, pattern, i))
+			return GIT_EINVALIDPATH;
+	}
+
+	error =  gitfo_prettify_dir_path(buffer_out, path);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	path_len = strlen(buffer_out);
+	if (path_len < 2)
+		return GIT_EINVALIDPATH;
+
+	/* Remove the trailing slash */
+	buffer_out[path_len - 1] = '\0';
+
+	return GIT_SUCCESS;
+}
+
+int gitfo_cmp_path(const char *name1, int len1, int isdir1,
+		const char *name2, int len2, int isdir2)
+{
+	int len = len1 < len2 ? len1 : len2;
+	int cmp;
+
+	cmp = memcmp(name1, name2, len);
+	if (cmp)
+		return cmp;
+	if (len1 < len2)
+		return ((!isdir1 && !isdir2) ? -1 :
+                        (isdir1 ? '/' - name2[len1] : name2[len1] - '/'));
+	if (len1 > len2)
+		return ((!isdir1 && !isdir2) ? 1 :
+                        (isdir2 ? name1[len2] - '/' : '/' - name1[len2]));
+	return 0;
+}
+
diff --git a/libgit2/src/fileops.h b/libgit2/src/fileops.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/fileops.h
@@ -0,0 +1,191 @@
+/*
+ * fileops.h - OS agnostic disk io operations
+ *
+ * This header describes the strictly internal part of the api
+ */
+#ifndef INCLUDE_fileops_h__
+#define INCLUDE_fileops_h__
+
+#include "common.h"
+#include "map.h"
+#include "dir.h"
+#include <fcntl.h>
+#include <time.h>
+
+#ifdef GIT_WIN32
+GIT_INLINE(int) link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
+{
+	GIT_UNUSED_ARG(old)
+	GIT_UNUSED_ARG(new)
+	errno = ENOSYS;
+	return -1;
+}
+
+GIT_INLINE(int) git__mkdir(const char *path, int GIT_UNUSED(mode))
+{
+	GIT_UNUSED_ARG(mode)
+	return mkdir(path);
+}
+
+extern int git__unlink(const char *path);
+extern int git__mkstemp(char *template);
+extern int git__fsync(int fd);
+
+# ifndef GIT__WIN32_NO_HIDE_FILEOPS
+#  define unlink(p) git__unlink(p)
+#  define mkstemp(t) git__mkstemp(t)
+#  define mkdir(p,m) git__mkdir(p, m)
+#  define fsync(fd) git__fsync(fd)
+# endif
+#endif  /* GIT_WIN32 */
+
+
+#if !defined(O_BINARY)
+#define O_BINARY 0
+#endif
+
+#define GITFO_BUF_INIT {NULL, 0}
+
+typedef int git_file;
+typedef struct gitfo_cache gitfo_cache;
+
+typedef struct {  /* file io buffer  */
+	void *data;  /* data bytes   */
+	size_t len;  /* data length  */
+} gitfo_buf;
+
+extern int gitfo_exists(const char *path);
+extern int gitfo_open(const char *path, int flags);
+extern int gitfo_creat(const char *path, int mode);
+extern int gitfo_creat_force(const char *path, int mode);
+extern int gitfo_isdir(const char *path);
+extern int gitfo_mkdir_recurs(const char *path, int mode);
+#define gitfo_close(fd) close(fd)
+
+extern int gitfo_read(git_file fd, void *buf, size_t cnt);
+extern int gitfo_write(git_file fd, void *buf, size_t cnt);
+#define gitfo_lseek(f,n,w) lseek(f, n, w)
+extern git_off_t gitfo_size(git_file fd);
+
+extern int gitfo_read_file(gitfo_buf *obj, const char *path);
+extern void gitfo_free_buf(gitfo_buf *obj);
+
+/* Move (rename) a file; this operation is atomic */
+extern int gitfo_mv(const char *from, const char *to);
+
+/* Move a file (forced); this will create the destination
+ * path if it doesn't exist */
+extern int gitfo_mv_force(const char *from, const char *to);
+
+#define gitfo_stat(p,b) stat(p, b)
+#define gitfo_fstat(f,b) fstat(f, b)
+
+#define gitfo_unlink(p) unlink(p)
+#define gitfo_rmdir(p) rmdir(p)
+#define gitfo_chdir(p) chdir(p)
+#define gitfo_mkdir(p,m) mkdir(p, m)
+
+#define gitfo_mkstemp(t) mkstemp(t)
+#define gitfo_fsync(fd) fsync(fd)
+#define gitfo_chmod(p,m) chmod(p, m)
+
+/**
+ * Read-only map all or part of a file into memory.
+ * When possible this function should favor a virtual memory
+ * style mapping over some form of malloc()+read(), as the
+ * data access will be random and is not likely to touch the
+ * majority of the region requested.
+ *
+ * @param out buffer to populate with the mapping information.
+ * @param fd open descriptor to configure the mapping from.
+ * @param begin first byte to map, this should be page aligned.
+ * @param end number of bytes to map.
+ * @return
+ * - GIT_SUCCESS on success;
+ * - GIT_EOSERR on an unspecified OS related error.
+ */
+extern int gitfo_map_ro(
+	git_map *out,
+	git_file fd,
+	git_off_t begin,
+	size_t len);
+
+/**
+ * Release the memory associated with a previous memory mapping.
+ * @param map the mapping description previously configured.
+ */
+extern void gitfo_free_map(git_map *map);
+
+/**
+ * Walk each directory entry, except '.' and '..', calling fn(state).
+ *
+ * @param pathbuf buffer the function reads the initial directory
+ * 		path from, and updates with each successive entry's name.
+ * @param pathmax maximum allocation of pathbuf.
+ * @param fn function to invoke with each entry.  The first arg is
+ *		the input state and the second arg is pathbuf.  The function
+ *		may modify the pathbuf, but only by appending new text.
+ * @param state to pass to fn as the first arg.
+ */
+extern int gitfo_dirent(
+	char *pathbuf,
+	size_t pathmax,
+	int (*fn)(void *, char *),
+	void *state);
+
+extern gitfo_cache *gitfo_enable_caching(git_file fd, size_t cache_size);
+extern int gitfo_write_cached(gitfo_cache *ioc, void *buf, size_t len);
+extern int gitfo_flush_cached(gitfo_cache *ioc);
+extern int gitfo_close_cached(gitfo_cache *ioc);
+
+
+extern int gitfo_cmp_path(const char *name1, int len1, int isdir1,
+		const char *name2, int len2, int isdir2);
+
+/**
+ * Clean up a provided absolute or relative directory path.
+ * 
+ * This prettification relies on basic operations such as coalescing 
+ * multiple forward slashes into a single slash, removing '.' and 
+ * './' current directory segments, and removing parent directory 
+ * whenever '..' is encountered.
+ *
+ * If not empty, the returned path ends with a forward slash.
+ *
+ * For instance, this will turn "d1/s1///s2/..//../s3" into "d1/s3/".
+ *
+ * This only performs a string based analysis of the path.
+ * No checks are done to make sure the path actually makes sense from 
+ * the file system perspective.
+ *
+ * @param buffer_out buffer to populate with the normalized path.
+ * @param path directory path to clean up.
+ * @return
+ * - GIT_SUCCESS on success;
+ * - GIT_ERROR when the input path is invalid or escapes the current directory.
+ */
+GIT_EXTERN(int) gitfo_prettify_dir_path(char *buffer_out, const char *path);
+
+/**
+ * Clean up a provided absolute or relative file path.
+ * 
+ * This prettification relies on basic operations such as coalescing 
+ * multiple forward slashes into a single slash, removing '.' and 
+ * './' current directory segments, and removing parent directory 
+ * whenever '..' is encountered.
+ *
+ * For instance, this will turn "d1/s1///s2/..//../s3" into "d1/s3".
+ *
+ * This only performs a string based analysis of the path.
+ * No checks are done to make sure the path actually makes sense from 
+ * the file system perspective.
+ *
+ * @param buffer_out buffer to populate with the normalized path.
+ * @param path file path to clean up.
+ * @return
+ * - GIT_SUCCESS on success;
+ * - GIT_ERROR when the input path is invalid or escapes the current directory.
+ */
+GIT_EXTERN(int) gitfo_prettify_file_path(char *buffer_out, const char *path);
+
+#endif /* INCLUDE_fileops_h__ */
diff --git a/libgit2/src/hash.c b/libgit2/src/hash.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/hash.c
@@ -0,0 +1,94 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "hash.h"
+
+#if defined(PPC_SHA1)
+# include "ppc/sha1.h"
+#elif defined(OPENSSL_SHA1)
+# include <openssl/sha.h>
+#else
+# include "block-sha1/sha1.h"
+#endif
+
+struct git_hash_ctx {
+	SHA_CTX c;
+};
+
+git_hash_ctx *git_hash_new_ctx(void)
+{
+	git_hash_ctx *ctx = git__malloc(sizeof(*ctx));
+
+	if (!ctx)
+		return NULL;
+
+	SHA1_Init(&ctx->c);
+
+	return ctx;
+}
+
+void git_hash_free_ctx(git_hash_ctx *ctx)
+{
+	free(ctx);
+}
+
+void git_hash_init(git_hash_ctx *ctx)
+{
+	assert(ctx);
+	SHA1_Init(&ctx->c);
+}
+
+void git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
+{
+	assert(ctx);
+	SHA1_Update(&ctx->c, data, len);
+}
+
+void git_hash_final(git_oid *out, git_hash_ctx *ctx)
+{
+	assert(ctx);
+	SHA1_Final(out->id, &ctx->c);
+}
+
+void git_hash_buf(git_oid *out, const void *data, size_t len)
+{
+	SHA_CTX c;
+
+	SHA1_Init(&c);
+	SHA1_Update(&c, data, len);
+	SHA1_Final(out->id, &c);
+}
+
+void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n)
+{
+	SHA_CTX c;
+	size_t i;
+
+	SHA1_Init(&c);
+	for (i = 0; i < n; i++)
+		SHA1_Update(&c, vec[i].data, vec[i].len);
+	SHA1_Final(out->id, &c);
+}
diff --git a/libgit2/src/hash.h b/libgit2/src/hash.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/hash.h
@@ -0,0 +1,26 @@
+/*
+ * hash.h
+ */
+#ifndef INCLUDE_hash_h__
+#define INCLUDE_hash_h__
+
+#include "git2/oid.h"
+
+typedef struct git_hash_ctx git_hash_ctx;
+
+typedef struct {
+	void *data;
+	size_t len;
+} git_buf_vec;
+
+git_hash_ctx *git_hash_new_ctx(void);
+void git_hash_free_ctx(git_hash_ctx *ctx);
+
+void git_hash_init(git_hash_ctx *c);
+void git_hash_update(git_hash_ctx *c, const void *data, size_t len);
+void git_hash_final(git_oid *out, git_hash_ctx *c);
+
+void git_hash_buf(git_oid *out, const void *data, size_t len);
+void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n);
+
+#endif /* INCLUDE_hash_h__ */
diff --git a/libgit2/src/hashtable.c b/libgit2/src/hashtable.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/hashtable.c
@@ -0,0 +1,261 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "repository.h"
+#include "commit.h"
+
+#define MAX_LOOPS 5
+static const double max_load_factor = 0.65;
+
+static int resize_to(git_hashtable *self, size_t new_size);
+static int set_size(git_hashtable *self, size_t new_size);
+static git_hashtable_node *node_with_hash(git_hashtable *self, const void *key, int hash_id);
+static void node_swap_with(git_hashtable_node *self, git_hashtable_node *other);
+static int node_insert(git_hashtable *self, git_hashtable_node *new_node);
+static int insert_nodes(git_hashtable *self, git_hashtable_node *old_nodes, size_t old_size);
+
+static int resize_to(git_hashtable *self, size_t new_size)
+{
+	git_hashtable_node *old_nodes = self->nodes;
+	size_t old_size = self->size;
+
+	self->is_resizing = 1;
+
+	do {
+		self->size = new_size;
+		self->size_mask = new_size - 1;
+		self->key_count = 0;
+		self->nodes = git__calloc(1, sizeof(git_hashtable_node) * self->size);
+
+		if (self->nodes == NULL)
+			return GIT_ENOMEM;
+
+		if (insert_nodes(self, old_nodes, old_size) == 0)
+			self->is_resizing = 0;
+		else {
+			new_size *= 2;
+			free(self->nodes);
+		}
+	} while(self->is_resizing);
+
+	free(old_nodes);
+	return GIT_SUCCESS;
+}
+
+static int set_size(git_hashtable *self, size_t new_size)
+{
+	self->nodes = realloc(self->nodes, new_size * sizeof(git_hashtable_node));
+	if (self->nodes == NULL)
+		return GIT_ENOMEM;
+
+	if (new_size > self->size) {
+		memset(&self->nodes[self->size], 0x0, (new_size - self->size) * sizeof(git_hashtable_node));
+	}
+
+	self->size = new_size;
+	self->size_mask = new_size - 1;
+	return GIT_SUCCESS;
+}
+
+static git_hashtable_node *node_with_hash(git_hashtable *self, const void *key, int hash_id)
+{
+	size_t pos = self->hash(key, hash_id) & self->size_mask;
+	return git_hashtable_node_at(self->nodes, pos);
+}
+
+static void node_swap_with(git_hashtable_node *self, git_hashtable_node *other)
+{
+	git_hashtable_node tmp = *self;
+	*self = *other;
+	*other = tmp;
+}
+
+static int node_insert(git_hashtable *self, git_hashtable_node *new_node)
+{	
+	int iteration, hash_id;
+
+	for (iteration = 0; iteration < MAX_LOOPS; iteration++) { 
+		for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
+			git_hashtable_node *node;
+			node = node_with_hash(self, new_node->key, hash_id);
+			node_swap_with(new_node, node);
+			if(new_node->key == 0x0){
+				self->key_count++;
+				return GIT_SUCCESS; 
+			}
+		}
+	}
+
+	if (self->is_resizing) 
+		return GIT_EBUSY;
+
+	resize_to(self, self->size * 2);
+	git_hashtable_insert(self, new_node->key, new_node->value);
+	return GIT_SUCCESS;
+}
+
+static int insert_nodes(git_hashtable *self, git_hashtable_node *old_nodes, size_t old_size)
+{
+	size_t i;
+
+	for (i = 0; i < old_size; ++i) {
+		git_hashtable_node *node = git_hashtable_node_at(old_nodes, i);
+		if (node->key && git_hashtable_insert(self, node->key, node->value) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+	}
+
+	return GIT_SUCCESS;
+}
+
+git_hashtable *git_hashtable_alloc(size_t min_size, 
+		git_hash_ptr hash,
+		git_hash_keyeq_ptr key_eq)
+{
+	git_hashtable *table;
+
+	assert(hash && key_eq);
+
+	if ((table = git__malloc(sizeof(git_hashtable))) == NULL)
+		return NULL;
+
+	memset(table, 0x0, sizeof(git_hashtable));
+
+	if (min_size < 8)
+		min_size = 8;
+
+	/* round up size to closest power of 2 */
+	min_size--;
+	min_size |= min_size >> 1;
+	min_size |= min_size >> 2;
+	min_size |= min_size >> 4;
+	min_size |= min_size >> 8;
+	min_size |= min_size >> 16;
+
+	table->hash = hash;
+	table->key_equal = key_eq;
+
+	set_size(table, min_size + 1);
+
+	return table;
+}
+
+void git_hashtable_clear(git_hashtable *self)
+{
+	assert(self);
+
+	memset(self->nodes, 0x0, sizeof(git_hashtable_node) * self->size);
+	self->key_count = 0;
+}
+
+void git_hashtable_free(git_hashtable *self)
+{
+	assert(self);
+
+	free(self->nodes);
+	free(self);
+}
+
+
+int git_hashtable_insert2(git_hashtable *self, const void *key, void *value, void **old_value)
+{
+	int hash_id;
+	git_hashtable_node *node;
+
+	assert(self && self->nodes);
+
+	*old_value = NULL;
+
+	for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
+		node = node_with_hash(self, key, hash_id);
+
+		if (!node->key) {
+			node->key = key;
+			node->value = value;
+			self->key_count++;
+			return GIT_SUCCESS;
+		}
+
+		if (key == node->key || self->key_equal(key, node->key) == 0) {
+			*old_value = node->value;
+			node->key = key;
+			node->value = value;
+			return GIT_SUCCESS;
+		}
+	}
+
+	/* no space in table; must do cuckoo dance */
+	{
+		git_hashtable_node x;
+		x.key = key;
+		x.value = value;
+		return node_insert(self, &x);
+	}
+}
+
+void *git_hashtable_lookup(git_hashtable *self, const void *key)
+{
+	int hash_id;
+	git_hashtable_node *node;
+
+	assert(self && self->nodes);
+
+	for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
+		node = node_with_hash(self, key, hash_id);
+		if (node->key && self->key_equal(key, node->key) == 0)
+			return node->value;
+	}
+
+	return NULL;
+}
+
+int git_hashtable_remove(git_hashtable *self, const void *key)
+{
+	int hash_id;
+	git_hashtable_node *node;
+
+	assert(self && self->nodes);
+
+	for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
+		node = node_with_hash(self, key, hash_id);
+		if (node->key && self->key_equal(key, node->key) == 0) {
+			node->key = NULL;
+			node->value = NULL;
+			self->key_count--;
+			return GIT_SUCCESS;
+		}
+	}
+
+	return GIT_ENOTFOUND;
+}
+
+int git_hashtable_merge(git_hashtable *self, git_hashtable *other)
+{
+	if (resize_to(self, (self->size + other->size) * 2) < GIT_SUCCESS)
+		return GIT_ENOMEM;
+
+	return insert_nodes(self, other->nodes, other->key_count);
+}
+
diff --git a/libgit2/src/hashtable.h b/libgit2/src/hashtable.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/hashtable.h
@@ -0,0 +1,73 @@
+#ifndef INCLUDE_hashtable_h__
+#define INCLUDE_hashtable_h__
+
+#include "git2/common.h"
+#include "git2/oid.h"
+#include "git2/odb.h"
+
+#define GIT_HASHTABLE_HASHES 3
+
+typedef uint32_t (*git_hash_ptr)(const void *, int hash_id);
+typedef int (*git_hash_keyeq_ptr)(const void *key_a, const void *key_b);
+
+struct git_hashtable_node {
+	const void *key;
+	void *value;
+};
+
+struct git_hashtable {
+	struct git_hashtable_node *nodes;
+
+	size_t size_mask;
+	size_t size;
+	size_t key_count;
+
+	int is_resizing;
+
+	git_hash_ptr hash;
+	git_hash_keyeq_ptr key_equal;
+};
+
+typedef struct git_hashtable_node git_hashtable_node;
+typedef struct git_hashtable git_hashtable;
+
+git_hashtable *git_hashtable_alloc(size_t min_size, 
+		git_hash_ptr hash,
+		git_hash_keyeq_ptr key_eq);
+void *git_hashtable_lookup(git_hashtable *h, const void *key);
+int git_hashtable_remove(git_hashtable *table, const void *key);
+void git_hashtable_free(git_hashtable *h);
+void git_hashtable_clear(git_hashtable *h);
+int git_hashtable_merge(git_hashtable *self, git_hashtable *other);
+
+int git_hashtable_insert2(git_hashtable *h, const void *key, void *value, void **old_value);
+
+GIT_INLINE(int) git_hashtable_insert(git_hashtable *h, const void *key, void *value)
+{
+	void *_unused;
+	return git_hashtable_insert2(h, key, value, &_unused);
+}
+
+#define git_hashtable_node_at(nodes, pos) ((git_hashtable_node *)(&nodes[pos]))
+
+#define GIT_HASHTABLE_FOREACH(self, pkey, pvalue, code) {\
+	git_hashtable *_self = (self);\
+	git_hashtable_node *_nodes = _self->nodes;\
+	unsigned int _i, _size = _self->size;\
+	for (_i = 0; _i < _size; _i ++) {\
+		git_hashtable_node *_node = git_hashtable_node_at(_nodes, _i);\
+		if (_node->key)\
+		{\
+			pkey = _node->key;\
+			pvalue = _node->value;\
+			code;\
+		}\
+	}\
+}
+
+#define GIT_HASHTABLE_FOREACH_DELETE() {\
+	_node->key = NULL; _node->value = NULL; _self->key_count--;\
+}
+
+
+#endif
diff --git a/libgit2/src/index.c b/libgit2/src/index.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/index.c
@@ -0,0 +1,768 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stddef.h>
+
+#include "common.h"
+#include "repository.h"
+#include "index.h"
+#include "hash.h"
+#include "git2/odb.h"
+#include "git2/blob.h"
+
+#define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
+#define short_entry_size(len) entry_size(struct entry_short, len)
+#define long_entry_size(len) entry_size(struct entry_long, len)
+
+#define minimal_entry_size (offsetof(struct entry_short, path))
+
+static const size_t INDEX_FOOTER_SIZE = GIT_OID_RAWSZ;
+static const size_t INDEX_HEADER_SIZE = 12;
+
+static const unsigned int INDEX_VERSION_NUMBER = 2;
+static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
+
+static const unsigned int INDEX_HEADER_SIG = 0x44495243;
+static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
+
+struct index_header {
+	uint32_t signature;
+	uint32_t version;
+	uint32_t entry_count;
+};
+
+struct index_extension {
+	char signature[4];
+	uint32_t extension_size;
+};
+
+struct entry_time {
+	uint32_t seconds;
+	uint32_t nanoseconds;
+};
+
+struct entry_short {
+	struct entry_time ctime;
+	struct entry_time mtime;
+	uint32_t dev;
+	uint32_t ino;
+	uint32_t mode;
+	uint32_t uid;
+	uint32_t gid;
+	uint32_t file_size;
+	git_oid oid;
+	uint16_t flags;
+	char path[1]; /* arbritrary length */
+};
+
+struct entry_long {
+	struct entry_time ctime;
+	struct entry_time mtime;
+	uint32_t dev;
+	uint32_t ino;
+	uint32_t mode;
+	uint32_t uid;
+	uint32_t gid;
+	uint32_t file_size;
+	git_oid oid;
+	uint16_t flags;
+	uint16_t flags_extended;
+	char path[1]; /* arbritrary length */
+};
+
+/* local declarations */
+static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size);
+static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size);
+static int read_header(struct index_header *dest, const void *buffer);
+
+static int read_tree(git_index *index, const char *buffer, size_t buffer_size);
+static git_index_tree *read_tree_internal(const char **, const char *, git_index_tree *);
+
+static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
+static void sort_index(git_index *index);
+static int write_index(git_index *index, git_filebuf *file);
+
+int index_srch(const void *key, const void *array_member)
+{
+	const char *filename = (const char *)key;
+	const git_index_entry *entry = *(const git_index_entry **)(array_member);
+
+	return strcmp(filename, entry->path);
+}
+
+int index_cmp(const void *a, const void *b)
+{
+	const git_index_entry *entry_a = *(const git_index_entry **)(a);
+	const git_index_entry *entry_b = *(const git_index_entry **)(b);
+
+	return strcmp(entry_a->path, entry_b->path);
+}
+
+
+static int index_initialize(git_index **index_out, git_repository *owner, const char *index_path)
+{
+	git_index *index;
+
+	assert(index_out && index_path);
+
+	index = git__malloc(sizeof(git_index));
+	if (index == NULL)
+		return GIT_ENOMEM;
+
+	memset(index, 0x0, sizeof(git_index));
+
+	index->index_file_path = git__strdup(index_path);
+	if (index->index_file_path == NULL) {
+		free(index);
+		return GIT_ENOMEM;
+	}
+
+	index->repository = owner;
+
+	git_vector_init(&index->entries, 32, index_cmp);
+
+	/* Check if index file is stored on disk already */
+	if (gitfo_exists(index->index_file_path) == 0)
+		index->on_disk = 1;
+
+	*index_out = index;
+	return GIT_SUCCESS;
+}
+
+int git_index_open_bare(git_index **index_out, const char *index_path)
+{
+	return index_initialize(index_out, NULL, index_path);
+}
+
+int git_index_open_inrepo(git_index **index_out, git_repository *repo)
+{
+	if (repo->is_bare)
+		return GIT_EBAREINDEX;
+
+	return index_initialize(index_out, repo, repo->path_index);
+}
+
+void git_index_free(git_index *index)
+{
+	if (index == NULL || index->repository != NULL)
+		return;
+
+	git_index_clear(index);
+	git_vector_free(&index->entries);
+
+	free(index->index_file_path);
+	free(index);
+}
+
+static void free_tree(git_index_tree *tree)
+{
+	unsigned int i;
+
+	if (tree == NULL)
+		return;
+
+	for (i = 0; i < tree->children_count; ++i)
+		free_tree(tree->children[i]);
+
+	free(tree->name);
+	free(tree->children);
+	free(tree);
+}
+
+void git_index_clear(git_index *index)
+{
+	unsigned int i;
+
+	assert(index);
+
+	for (i = 0; i < index->entries.length; ++i) {
+		git_index_entry *e;
+		e = git_vector_get(&index->entries, i);
+		free(e->path);
+		free(e);
+	}
+
+	git_vector_clear(&index->entries);
+	index->last_modified = 0;
+
+	free_tree(index->tree);
+	index->tree = NULL;
+}
+
+int git_index_read(git_index *index)
+{
+	struct stat indexst;
+	int error = GIT_SUCCESS;
+
+	assert(index->index_file_path);
+
+	if (!index->on_disk || gitfo_exists(index->index_file_path) < 0) {
+		git_index_clear(index);
+		index->on_disk = 0;
+		return GIT_SUCCESS;
+	}
+
+	if (gitfo_stat(index->index_file_path, &indexst) < 0)
+		return GIT_EOSERR;
+
+	if (!S_ISREG(indexst.st_mode))
+		return GIT_ENOTFOUND;
+
+	if (indexst.st_mtime != index->last_modified) {
+
+		gitfo_buf buffer;
+
+		if (gitfo_read_file(&buffer, index->index_file_path) < GIT_SUCCESS)
+			return GIT_EOSERR;
+
+		git_index_clear(index);
+		error = parse_index(index, buffer.data, buffer.len);
+
+		if (error == GIT_SUCCESS)
+			index->last_modified = indexst.st_mtime;
+
+		gitfo_free_buf(&buffer);
+	}
+
+	return error;
+}
+
+int git_index_write(git_index *index)
+{
+	git_filebuf file;
+	struct stat indexst;
+	int error;
+
+	sort_index(index);
+
+	if ((error = git_filebuf_open(&file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS)) < GIT_SUCCESS)
+		return error;
+
+	if ((error = write_index(index, &file)) < GIT_SUCCESS) {
+		git_filebuf_cleanup(&file);
+		return error;
+	}
+
+	if ((error = git_filebuf_commit(&file)) < GIT_SUCCESS)
+		return error;
+
+	if (gitfo_stat(index->index_file_path, &indexst) == 0) {
+		index->last_modified = indexst.st_mtime;
+		index->on_disk = 1;
+	}
+
+	return GIT_SUCCESS;
+}
+
+unsigned int git_index_entrycount(git_index *index)
+{
+	assert(index);
+	return index->entries.length;
+}
+
+git_index_entry *git_index_get(git_index *index, int n)
+{
+	assert(index);
+	sort_index(index);
+	return git_vector_get(&index->entries, (unsigned int)n);
+}
+
+int git_index_add(git_index *index, const char *rel_path, int stage)
+{
+	git_index_entry entry;
+	char full_path[GIT_PATH_MAX];
+	struct stat st;
+	int error;
+
+	if (index->repository == NULL)
+		return GIT_EBAREINDEX;
+
+	git__joinpath(full_path, index->repository->path_workdir, rel_path);
+
+	if (gitfo_exists(full_path) < 0)
+		return GIT_ENOTFOUND;
+
+	if (gitfo_stat(full_path, &st) < 0)
+		return GIT_EOSERR;
+
+	if (stage < 0 || stage > 3)
+		return GIT_ERROR;
+
+	memset(&entry, 0x0, sizeof(git_index_entry));
+
+	entry.ctime.seconds = st.st_ctime;
+	entry.mtime.seconds = st.st_mtime;
+	/* entry.mtime.nanoseconds = st.st_mtimensec; */
+	/* entry.ctime.nanoseconds = st.st_ctimensec; */
+	entry.dev= st.st_rdev;
+	entry.ino = st.st_ino;
+	entry.mode = st.st_mode;
+	entry.uid = st.st_uid;
+	entry.gid = st.st_gid;
+	entry.file_size = st.st_size;
+
+	/* write the blob to disk and get the oid */
+	if ((error = git_blob_writefile(&entry.oid, index->repository, full_path)) < GIT_SUCCESS)
+		return error;
+
+	entry.flags |= (stage << GIT_IDXENTRY_STAGESHIFT);
+	entry.path = (char *)rel_path; /* do not duplicate; index_insert already does this */
+
+	return git_index_insert(index, &entry);
+}
+
+void sort_index(git_index *index)
+{
+	git_vector_sort(&index->entries);
+}
+
+int git_index_insert(git_index *index, const git_index_entry *source_entry)
+{
+	git_index_entry *entry;
+	size_t path_length;
+	int position;
+
+	assert(index && source_entry);
+
+	if (source_entry->path == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	entry = git__malloc(sizeof(git_index_entry));
+	if (entry == NULL)
+		return GIT_ENOMEM;
+
+	memcpy(entry, source_entry, sizeof(git_index_entry));
+
+	/* duplicate the path string so we own it */
+	entry->path = git__strdup(entry->path);
+	if (entry->path == NULL)
+		return GIT_ENOMEM;
+
+	/* make sure that the path length flag is correct */
+	path_length = strlen(entry->path);
+
+	entry->flags &= ~GIT_IDXENTRY_NAMEMASK;
+
+	if (path_length < GIT_IDXENTRY_NAMEMASK)
+		entry->flags |= path_length & GIT_IDXENTRY_NAMEMASK;
+	else
+		entry->flags |= GIT_IDXENTRY_NAMEMASK;;
+
+
+	/* look if an entry with this path already exists */
+	position = git_index_find(index, source_entry->path);
+
+	/* if no entry exists, add the entry at the end;
+	 * the index is no longer sorted */
+	if (position == GIT_ENOTFOUND) {
+		if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+
+	/* if a previous entry exists, replace it */
+	} else {
+		git_index_entry **entry_array = (git_index_entry **)index->entries.contents;
+
+		free(entry_array[position]->path);
+		free(entry_array[position]);
+
+		entry_array[position] = entry;
+	}
+
+	return GIT_SUCCESS;
+}
+
+int git_index_remove(git_index *index, int position)
+{
+	assert(index);
+	sort_index(index);
+	return git_vector_remove(&index->entries, (unsigned int)position);
+}
+
+int git_index_find(git_index *index, const char *path)
+{
+	sort_index(index);
+	return git_vector_bsearch2(&index->entries, index_srch, path);
+}
+
+static git_index_tree *read_tree_internal(
+		const char **buffer_in, const char *buffer_end, git_index_tree *parent)
+{
+	git_index_tree *tree;
+	const char *name_start, *buffer;
+
+	if ((tree = git__malloc(sizeof(git_index_tree))) == NULL)
+		return NULL;
+
+	memset(tree, 0x0, sizeof(git_index_tree));
+	tree->parent = parent;
+
+	buffer = name_start = *buffer_in;
+
+	if ((buffer = memchr(buffer, '\0', buffer_end - buffer)) == NULL)
+		goto error_cleanup;
+
+	/* NUL-terminated tree name */
+	tree->name = git__strdup(name_start);
+	if (++buffer >= buffer_end)
+		goto error_cleanup;
+
+	/* Blank-terminated ASCII decimal number of entries in this tree */
+	tree->entries = strtol(buffer, (char **)&buffer, 10);
+	if (*buffer != ' ' || ++buffer >= buffer_end)
+		goto error_cleanup;
+
+	 /* Number of children of the tree, newline-terminated */
+	tree->children_count = strtol(buffer, (char **)&buffer, 10);
+	if (*buffer != '\n' || ++buffer >= buffer_end)
+		goto error_cleanup;
+
+	/* 160-bit SHA-1 for this tree and it's children */
+	if (buffer + GIT_OID_RAWSZ > buffer_end)
+		goto error_cleanup;
+
+	git_oid_mkraw(&tree->oid, (const unsigned char *)buffer);
+	buffer += GIT_OID_RAWSZ;
+
+	/* Parse children: */
+	if (tree->children_count > 0) {
+		unsigned int i;
+
+		tree->children = git__malloc(tree->children_count * sizeof(git_index_tree *));
+		if (tree->children == NULL)
+			goto error_cleanup;
+
+		for (i = 0; i < tree->children_count; ++i) {
+			tree->children[i] = read_tree_internal(&buffer, buffer_end, tree);
+
+			if (tree->children[i] == NULL)
+				goto error_cleanup;
+		}
+	}
+
+	*buffer_in = buffer;
+	return tree;
+
+error_cleanup:
+	free_tree(tree);
+	return NULL;
+}
+
+static int read_tree(git_index *index, const char *buffer, size_t buffer_size)
+{
+	const char *buffer_end = buffer + buffer_size;
+
+	index->tree = read_tree_internal(&buffer, buffer_end, NULL);
+	return (index->tree != NULL && buffer == buffer_end) ? GIT_SUCCESS : GIT_EOBJCORRUPTED;
+}
+
+static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size)
+{
+	size_t path_length, entry_size;
+	uint16_t flags_raw;
+	const char *path_ptr;
+	const struct entry_short *source;
+
+	if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
+		return 0;
+
+	memset(dest, 0x0, sizeof(git_index_entry));
+
+	source = (const struct entry_short *)(buffer);
+
+	dest->ctime.seconds = (time_t)ntohl(source->ctime.seconds);
+	dest->ctime.nanoseconds = (time_t)ntohl(source->ctime.nanoseconds);
+	dest->mtime.seconds = (time_t)ntohl(source->mtime.seconds);
+	dest->mtime.nanoseconds = (time_t)ntohl(source->mtime.nanoseconds);
+	dest->dev = ntohl(source->dev);
+	dest->ino = ntohl(source->ino);
+	dest->mode = ntohl(source->mode);
+	dest->uid = ntohl(source->uid);
+	dest->gid = ntohl(source->gid);
+	dest->file_size = ntohl(source->file_size);
+	git_oid_cpy(&dest->oid, &source->oid);
+	dest->flags = ntohs(source->flags);
+
+	if (dest->flags & GIT_IDXENTRY_EXTENDED) {
+		struct entry_long *source_l = (struct entry_long *)source;
+		path_ptr = source_l->path;
+
+		flags_raw = ntohs(source_l->flags_extended);
+		memcpy(&dest->flags_extended, &flags_raw, 2);
+	} else
+		path_ptr = source->path;
+
+	path_length = dest->flags & GIT_IDXENTRY_NAMEMASK;
+
+	/* if this is a very long string, we must find its
+	 * real length without overflowing */
+	if (path_length == 0xFFF) {
+		const char *path_end;
+
+		path_end = memchr(path_ptr, '\0', buffer_size);
+		if (path_end == NULL)
+			return 0;
+
+		path_length = path_end - path_ptr;
+	}
+
+	if (dest->flags & GIT_IDXENTRY_EXTENDED)
+		entry_size = long_entry_size(path_length);
+	else
+		entry_size = short_entry_size(path_length);
+
+	if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
+		return 0;
+
+	dest->path = git__strdup(path_ptr);
+	assert(dest->path);
+
+	return entry_size;
+}
+
+static int read_header(struct index_header *dest, const void *buffer)
+{
+	const struct index_header *source;
+	source = (const struct index_header *)(buffer);
+
+	dest->signature = ntohl(source->signature);
+	if (dest->signature != INDEX_HEADER_SIG)
+		return GIT_EOBJCORRUPTED;
+
+	dest->version = ntohl(source->version);
+	if (dest->version != INDEX_VERSION_NUMBER_EXT &&
+		dest->version != INDEX_VERSION_NUMBER)
+		return GIT_EOBJCORRUPTED;
+
+	dest->entry_count = ntohl(source->entry_count);
+	return GIT_SUCCESS;
+}
+
+static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size)
+{
+	const struct index_extension *source;
+	struct index_extension dest;
+	size_t total_size;
+
+	source = (const struct index_extension *)(buffer);
+
+	memcpy(dest.signature, source->signature, 4);
+	dest.extension_size = ntohl(source->extension_size);
+
+	total_size = dest.extension_size + sizeof(struct index_extension);
+
+	if (buffer_size - total_size < INDEX_FOOTER_SIZE)
+		return 0;
+
+	/* optional extension */
+	if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') {
+		/* tree cache */
+		if (memcmp(dest.signature, INDEX_EXT_TREECACHE_SIG, 4) == 0) {
+
+			if (read_tree(index, buffer + 8, dest.extension_size) < GIT_SUCCESS)
+				return 0;
+		}
+	} else {
+		/* we cannot handle non-ignorable extensions;
+		 * in fact they aren't even defined in the standard */
+		return 0;
+	}
+
+	return total_size;
+}
+
+static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
+{
+	unsigned int i;
+	struct index_header header;
+	git_oid checksum_calculated, checksum_expected;
+
+#define seek_forward(_increase) { \
+	if (_increase >= buffer_size) \
+		return GIT_EOBJCORRUPTED; \
+	buffer += _increase; \
+	buffer_size -= _increase;\
+}
+
+	if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE)
+		return GIT_EOBJCORRUPTED;
+
+	/* Precalculate the SHA1 of the files's contents -- we'll match it to
+	 * the provided SHA1 in the footer */
+	git_hash_buf(&checksum_calculated, (const void *)buffer, buffer_size - INDEX_FOOTER_SIZE);
+
+	/* Parse header */
+	if (read_header(&header, buffer) < GIT_SUCCESS)
+		return GIT_EOBJCORRUPTED;
+
+	seek_forward(INDEX_HEADER_SIZE);
+
+	git_vector_clear(&index->entries);
+
+	/* Parse all the entries */
+	for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
+		size_t entry_size;
+		git_index_entry *entry;
+
+		entry = git__malloc(sizeof(git_index_entry));
+		if (entry == NULL)
+			return GIT_ENOMEM;
+
+		entry_size = read_entry(entry, buffer, buffer_size);
+
+		/* 0 bytes read means an object corruption */
+		if (entry_size == 0)
+			return GIT_EOBJCORRUPTED;
+
+		if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+
+		seek_forward(entry_size);
+	}
+
+	if (i != header.entry_count)
+		return GIT_EOBJCORRUPTED;
+
+	/* There's still space for some extensions! */
+	while (buffer_size > INDEX_FOOTER_SIZE) {
+		size_t extension_size;
+
+		extension_size = read_extension(index, buffer, buffer_size);
+
+		/* see if we have read any bytes from the extension */
+		if (extension_size == 0)
+			return GIT_EOBJCORRUPTED;
+
+		seek_forward(extension_size);
+	}
+
+	if (buffer_size != INDEX_FOOTER_SIZE)
+		return GIT_EOBJCORRUPTED;
+
+	/* 160-bit SHA-1 over the content of the index file before this checksum. */
+	git_oid_mkraw(&checksum_expected, (const unsigned char *)buffer);
+
+	if (git_oid_cmp(&checksum_calculated, &checksum_expected) != 0)
+		return GIT_EOBJCORRUPTED;
+
+#undef seek_forward
+
+	/* force sorting in the vector: the entries are
+	 * assured to be sorted on the index */
+	index->entries.sorted = 1;
+	return GIT_SUCCESS;
+}
+
+static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
+{
+	struct entry_short *ondisk;
+	size_t path_len, disk_size;
+	char *path;
+
+	path_len = strlen(entry->path);
+
+	if (entry->flags & GIT_IDXENTRY_EXTENDED)
+		disk_size = long_entry_size(path_len);
+	else
+		disk_size = short_entry_size(path_len);
+
+	if (git_filebuf_reserve(file, (void **)&ondisk, disk_size) < GIT_SUCCESS)
+		return GIT_ENOMEM;
+
+	memset(ondisk, 0x0, disk_size);
+
+	ondisk->ctime.seconds = htonl((unsigned long)entry->ctime.seconds);
+	ondisk->mtime.seconds = htonl((unsigned long)entry->mtime.seconds);
+	ondisk->ctime.nanoseconds = htonl(entry->ctime.nanoseconds);
+	ondisk->mtime.nanoseconds = htonl(entry->mtime.nanoseconds);
+	ondisk->dev  = htonl(entry->dev);
+	ondisk->ino  = htonl(entry->ino);
+	ondisk->mode = htonl(entry->mode);
+	ondisk->uid  = htonl(entry->uid);
+	ondisk->gid  = htonl(entry->gid);
+	ondisk->file_size = htonl((unsigned long)entry->file_size);
+
+	git_oid_cpy(&ondisk->oid, &entry->oid);
+
+	ondisk->flags = htons(entry->flags);
+
+	if (entry->flags & GIT_IDXENTRY_EXTENDED) {
+		struct entry_long *ondisk_ext;
+		ondisk_ext = (struct entry_long *)ondisk;
+		ondisk_ext->flags_extended = htons(entry->flags_extended);
+		path = ondisk_ext->path;
+	}
+	else
+		path = ondisk->path;
+
+	memcpy(path, entry->path, path_len);
+
+	return GIT_SUCCESS;
+}
+
+static int write_entries(git_index *index, git_filebuf *file)
+{
+	unsigned int i;
+
+	for (i = 0; i < index->entries.length; ++i) {
+		git_index_entry *entry;
+		entry = git_vector_get(&index->entries, i);
+		if (write_disk_entry(file, entry) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+	}
+
+	return GIT_SUCCESS;
+}
+
+static int write_index(git_index *index, git_filebuf *file)
+{
+	int error = GIT_SUCCESS;
+	git_oid hash_final;
+
+	struct index_header header;
+
+	int is_extended = 1;
+
+	assert(index && file);
+
+	header.signature = htonl(INDEX_HEADER_SIG);
+	header.version = htonl(is_extended ? INDEX_VERSION_NUMBER : INDEX_VERSION_NUMBER_EXT);
+	header.entry_count = htonl(index->entries.length);
+
+	git_filebuf_write(file, &header, sizeof(struct index_header));
+
+	error = write_entries(index, file);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	/* TODO: write extensions (tree cache) */
+
+	/* get out the hash for all the contents we've appended to the file */
+	git_filebuf_hash(&hash_final, file);
+
+	/* write it at the end of the file */
+	git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ);
+
+	return error;
+}
diff --git a/libgit2/src/index.h b/libgit2/src/index.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/index.h
@@ -0,0 +1,34 @@
+#ifndef INCLUDE_index_h__
+#define INCLUDE_index_h__
+
+#include "fileops.h"
+#include "filebuf.h"
+#include "vector.h"
+#include "git2/odb.h"
+#include "git2/index.h"
+
+struct git_index_tree {
+	char *name;
+
+	struct git_index_tree *parent;
+	struct git_index_tree **children;
+	size_t children_count;
+
+	size_t entries;
+	git_oid oid;
+};
+
+typedef struct git_index_tree git_index_tree;
+
+struct git_index {
+	git_repository *repository;
+	char *index_file_path;
+
+	time_t last_modified;
+	git_vector entries;
+
+	unsigned int on_disk:1;
+	git_index_tree *tree;
+};
+
+#endif
diff --git a/libgit2/src/map.h b/libgit2/src/map.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/map.h
@@ -0,0 +1,31 @@
+#ifndef INCLUDE_map_h__
+#define INCLUDE_map_h__
+
+#include "common.h"
+
+
+/* git__mmap() prot values */
+#define GIT_PROT_NONE  0x0
+#define GIT_PROT_READ  0x1
+#define GIT_PROT_WRITE 0x2
+#define GIT_PROT_EXEC  0x4
+
+/* git__mmmap() flags values */
+#define GIT_MAP_FILE    0
+#define GIT_MAP_SHARED  1
+#define GIT_MAP_PRIVATE 2
+#define GIT_MAP_TYPE    0xf
+#define GIT_MAP_FIXED   0x10
+
+typedef struct {  /* memory mapped buffer   */
+	void *data;  /* data bytes          */
+	size_t len;  /* data length         */
+#ifdef GIT_WIN32
+	HANDLE fmh;  /* file mapping handle */
+#endif
+} git_map;
+
+extern int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset);
+extern int git__munmap(git_map *map);
+
+#endif /* INCLUDE_map_h__ */
diff --git a/libgit2/src/mingw-compat.h b/libgit2/src/mingw-compat.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/mingw-compat.h
@@ -0,0 +1,13 @@
+#ifndef INCLUDE_mingw_compat__
+#define INCLUDE_mingw_compat__
+
+#if defined(__MINGW32__)
+
+/* use a 64-bit file offset type */
+# define lseek _lseeki64
+# define stat _stati64
+# define fstat _fstati64
+
+#endif
+
+#endif /* INCLUDE_mingw_compat__ */
diff --git a/libgit2/src/msvc-compat.h b/libgit2/src/msvc-compat.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/msvc-compat.h
@@ -0,0 +1,42 @@
+#ifndef INCLUDE_msvc_compat__
+#define INCLUDE_msvc_compat__
+
+#if defined(_MSC_VER)
+
+/* access() mode parameter #defines   */
+# define F_OK 0  /* existence  check */
+# define W_OK 2  /* write mode check */
+# define R_OK 4  /* read  mode check */
+
+# define lseek _lseeki64
+# define stat _stat64
+# define fstat _fstat64
+
+/* stat: file mode type testing macros */
+# define S_ISDIR(m)   (((m) & _S_IFMT) == _S_IFDIR)
+# define S_ISREG(m)   (((m) & _S_IFMT) == _S_IFREG)
+# define S_ISFIFO(m)  (((m) & _S_IFMT) == _S_IFIFO)
+
+#if (_MSC_VER >= 1600)
+#	include <stdint.h>
+#else
+/* add some missing <stdint.h> typedef's */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+
+typedef short int16_t;
+typedef unsigned short uint16_t;
+
+typedef long int32_t;
+typedef unsigned long uint32_t;
+
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+typedef long long intmax_t;
+typedef unsigned long long uintmax_t;
+#endif
+
+#endif
+
+#endif /* INCLUDE_msvc_compat__ */
diff --git a/libgit2/src/object.c b/libgit2/src/object.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/object.c
@@ -0,0 +1,487 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <stdarg.h>
+
+#include "git2/object.h"
+
+#include "common.h"
+#include "repository.h"
+
+#include "commit.h"
+#include "tree.h"
+#include "blob.h"
+#include "tag.h"
+
+static const int OBJECT_BASE_SIZE = 4096;
+
+static struct {
+	const char	*str;   /* type name string */
+	int			loose;  /* valid loose object type flag */
+	size_t		size;	/* size in bytes of the object structure */
+} git_objects_table[] = {
+	/* 0 = GIT_OBJ__EXT1 */
+	{ "", 0, 0},
+
+	/* 1 = GIT_OBJ_COMMIT */
+	{ "commit", 1, sizeof(struct git_commit)},
+
+	/* 2 = GIT_OBJ_TREE */
+	{ "tree", 1, sizeof(struct git_tree) },
+
+	/* 3 = GIT_OBJ_BLOB */
+	{ "blob", 1, sizeof(struct git_blob) },
+
+	/* 4 = GIT_OBJ_TAG */
+	{ "tag", 1, sizeof(struct git_tag) },
+
+	/* 5 = GIT_OBJ__EXT2 */
+	{ "", 0, 0 },
+
+	/* 6 = GIT_OBJ_OFS_DELTA */
+	{ "OFS_DELTA", 0, 0 },
+
+	/* 7 = GIT_OBJ_REF_DELTA */
+	{ "REF_DELTA", 0, 0	}
+};
+
+/*
+ * Object source methods
+ *
+ * Abstract buffer methods that allow the writeback system
+ * to prepare the contents of any git file in-memory before
+ * writing them to disk.
+ */
+static int source_resize(git_odb_source *src)
+{
+	size_t write_offset, new_size;
+	void *new_data;
+
+	write_offset = (size_t)((char *)src->write_ptr - (char *)src->raw.data);
+
+	new_size = src->raw.len * 2;
+	if ((new_data = git__malloc(new_size)) == NULL)
+		return GIT_ENOMEM;
+
+	memcpy(new_data, src->raw.data, src->written_bytes);
+	free(src->raw.data);
+
+	src->raw.data = new_data;
+	src->raw.len = new_size;
+	src->write_ptr = (char *)new_data + write_offset;
+
+	return GIT_SUCCESS;
+}
+
+int git__source_printf(git_odb_source *source, const char *format, ...)
+{
+	va_list arglist;
+	int len;
+
+	assert(source->open && source->write_ptr);
+
+	va_start(arglist, format);
+
+	len = vsnprintf(source->write_ptr, source->raw.len - source->written_bytes, format, arglist);
+
+	while (source->written_bytes + len >= source->raw.len) {
+		if (source_resize(source) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+
+		len = vsnprintf(source->write_ptr, source->raw.len - source->written_bytes, format, arglist);
+	}
+
+	source->write_ptr = (char *)source->write_ptr + len;
+	source->written_bytes += len;
+
+	return GIT_SUCCESS;
+}
+
+int git__source_write(git_odb_source *source, const void *bytes, size_t len)
+{
+	assert(source);
+
+	assert(source->open && source->write_ptr);
+
+	while (source->written_bytes + len >= source->raw.len) {
+		if (source_resize(source) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+	}
+
+	memcpy(source->write_ptr, bytes, len);
+	source->write_ptr = (char *)source->write_ptr + len;
+	source->written_bytes += len;
+
+	return GIT_SUCCESS;
+}
+
+static void prepare_write(git_object *object)
+{
+	if (object->source.write_ptr != NULL || object->source.open)
+		git_object__source_close(object);
+
+	/* TODO: proper size calculation */
+	object->source.raw.data = git__malloc(OBJECT_BASE_SIZE);
+	object->source.raw.len = OBJECT_BASE_SIZE;
+
+	object->source.write_ptr = object->source.raw.data;
+	object->source.written_bytes = 0;
+
+	object->source.open = 1;
+}
+
+static int write_back(git_object *object)
+{
+	int error;
+	git_oid new_id;
+
+	assert(object);
+
+	assert(object->source.open);
+	assert(object->modified);
+
+	object->source.raw.len = object->source.written_bytes;
+
+	if ((error = git_odb_write(&new_id, object->repo->db, &object->source.raw)) < GIT_SUCCESS)
+		return error;
+
+	if (object->in_memory) {
+		int idx = git_vector_search(&object->repo->memory_objects, object);
+		git_vector_remove(&object->repo->memory_objects, idx);
+	} else {
+		git_hashtable_remove(object->repo->objects, &object->id);
+	}
+
+	git_oid_cpy(&object->id, &new_id);
+	git_hashtable_insert(object->repo->objects, &object->id, object);
+
+	object->source.write_ptr = NULL;
+	object->source.written_bytes = 0;
+
+	object->modified = 0;
+	object->in_memory = 0;
+
+	git_object__source_close(object);
+	return GIT_SUCCESS;
+}
+
+int git_object__source_open(git_object *object)
+{
+	int error;
+
+	assert(object && !object->in_memory);
+
+	if (object->source.open)
+		git_object__source_close(object);
+
+	error = git_odb_read(&object->source.raw, object->repo->db, &object->id);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	object->source.open = 1;
+	return GIT_SUCCESS;
+}
+
+void git_object__source_close(git_object *object)
+{
+	assert(object);
+
+	if (object->source.open) {
+		git_rawobj_close(&object->source.raw);
+		object->source.open = 0;
+	}
+}
+
+static int create_object(git_object **object_out, git_otype type)
+{
+	git_object *object = NULL;
+
+	assert(object_out);
+
+	*object_out = NULL;
+
+	switch (type) {
+	case GIT_OBJ_COMMIT:
+	case GIT_OBJ_TAG:
+	case GIT_OBJ_BLOB:
+		object = git__malloc(git_object__size(type));
+		if (object == NULL)
+			return GIT_ENOMEM;
+		memset(object, 0x0, git_object__size(type));
+		break;
+		
+	case GIT_OBJ_TREE:
+		object = (git_object *)git_tree__new();
+		if (object == NULL)
+			return GIT_ENOMEM;
+		break;
+
+	default:
+		return GIT_EINVALIDTYPE;
+	}
+
+	*object_out = object;
+	return GIT_SUCCESS;
+}
+
+int git_object_new(git_object **object_out, git_repository *repo, git_otype type)
+{
+	git_object *object = NULL;
+	int error;
+
+	assert(object_out && repo);
+
+	if ((error = create_object(&object, type)) < GIT_SUCCESS)
+		return error;
+
+	object->repo = repo;
+	object->in_memory = 1;
+	object->modified = 1;
+
+	object->source.raw.type = type;
+
+	object->lru = ++repo->lru_counter;
+	*object_out = object;
+	return GIT_SUCCESS;
+}
+
+int git_object_lookup(git_object **object_out, git_repository *repo, const git_oid *id, git_otype type)
+{
+	git_object *object = NULL;
+	git_rawobj obj_file;
+	int error = GIT_SUCCESS;
+
+	assert(repo && object_out && id);
+
+	object = git_hashtable_lookup(repo->objects, id);
+	if (object != NULL) {
+		if (type != GIT_OBJ_ANY && type != object->source.raw.type)
+			return GIT_EINVALIDTYPE;
+
+		*object_out = object;
+		object->lru = ++repo->lru_counter;
+		object->can_free = 0;
+		return GIT_SUCCESS;
+	}
+
+	error = git_odb_read(&obj_file, repo->db, id);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	if (type != GIT_OBJ_ANY && type != obj_file.type) {
+		git_rawobj_close(&obj_file);
+		return GIT_EINVALIDTYPE;
+	}
+
+	type = obj_file.type;
+
+	if ((error = create_object(&object, type)) < GIT_SUCCESS)
+		return error;
+
+	/* Initialize parent object */
+	git_oid_cpy(&object->id, id);
+	object->repo = repo;
+	memcpy(&object->source.raw, &obj_file, sizeof(git_rawobj));
+	object->source.open = 1;
+
+	switch (type) {
+	case GIT_OBJ_COMMIT:
+		error = git_commit__parse((git_commit *)object);
+		break;
+
+	case GIT_OBJ_TREE:
+		error = git_tree__parse((git_tree *)object);
+		break;
+
+	case GIT_OBJ_TAG:
+		error = git_tag__parse((git_tag *)object);
+		break;
+
+	case GIT_OBJ_BLOB:
+		error = git_blob__parse((git_blob *)object);
+		break;
+
+	default:
+		break;
+	}
+
+	if (error < GIT_SUCCESS) {
+		git_object__free(object);
+		return error;
+	}
+
+	git_object__source_close(object);
+	git_hashtable_insert(repo->objects, &object->id, object);
+
+	object->lru = ++repo->lru_counter;
+	*object_out = object;
+	return GIT_SUCCESS;
+}
+
+int git_object_write(git_object *object)
+{
+	int error;
+	git_odb_source *source;
+
+	assert(object);
+
+	if (object->modified == 0)
+		return GIT_SUCCESS;
+
+	prepare_write(object);
+	source = &object->source;
+
+	switch (source->raw.type) {
+	case GIT_OBJ_COMMIT:
+		error = git_commit__writeback((git_commit *)object, source);
+		break;
+
+	case GIT_OBJ_TREE:
+		error = git_tree__writeback((git_tree *)object, source);
+		break;
+
+	case GIT_OBJ_TAG:
+		error = git_tag__writeback((git_tag *)object, source);
+		break;
+
+	case GIT_OBJ_BLOB:
+		error = git_blob__writeback((git_blob *)object, source);
+		break;
+
+	default:
+		error = GIT_ERROR;
+		break;
+	}
+
+	if (error < GIT_SUCCESS) {
+		git_object__source_close(object);
+		return error;
+	}
+
+	return write_back(object);
+}
+
+void git_object__free(git_object *object)
+{
+	assert(object);
+
+	git_object__source_close(object);
+
+	switch (object->source.raw.type) {
+	case GIT_OBJ_COMMIT:
+		git_commit__free((git_commit *)object);
+		break;
+
+	case GIT_OBJ_TREE:
+		git_tree__free((git_tree *)object);
+		break;
+
+	case GIT_OBJ_TAG:
+		git_tag__free((git_tag *)object);
+		break;
+
+	case GIT_OBJ_BLOB:
+		git_blob__free((git_blob *)object);
+		break;
+
+	default:
+		free(object);
+		break;
+	}
+}
+
+void git_object_close(git_object *object)
+{
+	if (object == NULL)
+		return;
+
+	if (object->in_memory) {
+		int idx = git_vector_search(&object->repo->memory_objects, object);
+		git_vector_remove(&object->repo->memory_objects, idx);
+		git_object__free(object);
+	} else {
+		object->can_free = 1;
+	}
+}
+
+const git_oid *git_object_id(const git_object *obj)
+{
+	assert(obj);
+
+	if (obj->in_memory)
+		return NULL;
+
+	return &obj->id;
+}
+
+git_otype git_object_type(const git_object *obj)
+{
+	assert(obj);
+	return obj->source.raw.type;
+}
+
+git_repository *git_object_owner(const git_object *obj)
+{
+	assert(obj);
+	return obj->repo;
+}
+
+const char *git_object_type2string(git_otype type)
+{
+	if (type < 0 || ((size_t) type) >= ARRAY_SIZE(git_objects_table))
+		return "";
+
+	return git_objects_table[type].str;
+}
+
+git_otype git_object_string2type(const char *str)
+{
+	size_t i;
+
+	if (!str || !*str)
+		return GIT_OBJ_BAD;
+
+	for (i = 0; i < ARRAY_SIZE(git_objects_table); i++)
+		if (!strcmp(str, git_objects_table[i].str))
+			return (git_otype)i;
+
+	return GIT_OBJ_BAD;
+}
+
+int git_object_typeisloose(git_otype type)
+{
+	if (type < 0 || ((size_t) type) >= ARRAY_SIZE(git_objects_table))
+		return 0;
+
+	return git_objects_table[type].loose;
+}
+
+size_t git_object__size(git_otype type)
+{
+	if (type < 0 || ((size_t) type) >= ARRAY_SIZE(git_objects_table))
+		return 0;
+
+	return git_objects_table[type].size;
+}
+
diff --git a/libgit2/src/odb.c b/libgit2/src/odb.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/odb.c
@@ -0,0 +1,396 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "git2/zlib.h"
+#include "git2/object.h"
+#include "fileops.h"
+#include "hash.h"
+#include "odb.h"
+#include "delta-apply.h"
+
+#include "git2/odb_backend.h"
+
+#define GIT_ALTERNATES_FILE "info/alternates"
+
+/* TODO: is this correct? */
+#define GIT_LOOSE_PRIORITY 2
+#define GIT_PACKED_PRIORITY 1
+
+typedef struct
+{
+	git_odb_backend *backend;
+	int priority;
+	int is_alternate;
+} backend_internal;
+
+static int format_object_header(char *hdr, size_t n, git_rawobj *obj)
+{
+	const char *type_str = git_object_type2string(obj->type);
+	int len = snprintf(hdr, n, "%s %"PRIuZ, type_str, obj->len);
+
+	assert(len > 0);             /* otherwise snprintf() is broken  */
+	assert(((size_t) len) < n);  /* otherwise the caller is broken! */
+
+	if (len < 0 || ((size_t) len) >= n)
+		return GIT_ERROR;
+	return len+1;
+}
+
+int git_odb__hash_obj(git_oid *id, char *hdr, size_t n, int *len, git_rawobj *obj)
+{
+	git_buf_vec vec[2];
+	int  hdrlen;
+
+	assert(id && hdr && len && obj);
+
+	if (!git_object_typeisloose(obj->type))
+		return GIT_ERROR;
+
+	if (!obj->data && obj->len != 0)
+		return GIT_ERROR;
+
+	if ((hdrlen = format_object_header(hdr, n, obj)) < 0)
+		return GIT_ERROR;
+
+	*len = hdrlen;
+
+	vec[0].data = hdr;
+	vec[0].len  = hdrlen;
+	vec[1].data = obj->data;
+	vec[1].len  = obj->len;
+
+	git_hash_vec(id, vec, 2);
+
+	return GIT_SUCCESS;
+}
+
+void git_rawobj_close(git_rawobj *obj)
+{
+	free(obj->data);
+	obj->data = NULL;
+}
+
+int git_rawobj_hash(git_oid *id, git_rawobj *obj)
+{
+	char hdr[64];
+	int  hdrlen;
+
+	assert(id && obj);
+
+	return git_odb__hash_obj(id, hdr, sizeof(hdr), &hdrlen, obj);
+}
+
+int git_odb__inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
+{
+	z_stream zs;
+	int status = Z_OK;
+
+	memset(&zs, 0x0, sizeof(zs));
+
+	zs.next_out  = out;
+	zs.avail_out = outlen;
+
+	zs.next_in  = in;
+	zs.avail_in = inlen;
+
+	if (inflateInit(&zs) < Z_OK)
+		return GIT_ERROR;
+
+	while (status == Z_OK)
+		status = inflate(&zs, Z_FINISH);
+
+	inflateEnd(&zs);
+
+	if ((status != Z_STREAM_END) /*|| (zs.avail_in != 0) */)
+		return GIT_ERROR;
+
+	if (zs.total_out != outlen)
+		return GIT_ERROR;
+
+	return GIT_SUCCESS;
+}
+
+
+
+
+
+/***********************************************************
+ *
+ * OBJECT DATABASE PUBLIC API
+ *
+ * Public calls for the ODB functionality
+ *
+ ***********************************************************/
+
+int backend_sort_cmp(const void *a, const void *b)
+{
+	const backend_internal *backend_a = *(const backend_internal **)(a);
+	const backend_internal *backend_b = *(const backend_internal **)(b);
+
+	if (backend_a->is_alternate == backend_b->is_alternate)
+		return (backend_b->priority - backend_a->priority);
+
+	return backend_a->is_alternate ? 1 : -1;
+}
+
+int git_odb_new(git_odb **out)
+{
+	git_odb *db = git__calloc(1, sizeof(*db));
+	if (!db)
+		return GIT_ENOMEM;
+
+	if (git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) {
+		free(db);
+		return GIT_ENOMEM;
+	}
+
+	*out = db;
+	return GIT_SUCCESS;
+}
+
+static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int priority, int is_alternate)
+{
+	backend_internal *internal;
+
+	assert(odb && backend);
+
+	if (backend->odb != NULL && backend->odb != odb)
+		return GIT_EBUSY;
+
+	internal = git__malloc(sizeof(backend_internal));
+	if (internal == NULL)
+		return GIT_ENOMEM;
+
+	internal->backend = backend;
+	internal->priority = priority;
+	internal->is_alternate = is_alternate;
+
+	if (git_vector_insert(&odb->backends, internal) < 0) {
+		free(internal);
+		return GIT_ENOMEM;
+	}
+
+	git_vector_sort(&odb->backends);
+	internal->backend->odb = odb;
+	return GIT_SUCCESS;
+}
+
+int git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority)
+{
+	return add_backend_internal(odb, backend, priority, 0);
+}
+
+int git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority)
+{
+	return add_backend_internal(odb, backend, priority, 1);
+}
+
+static int add_default_backends(git_odb *db, const char *objects_dir, int as_alternates)
+{
+	git_odb_backend *loose, *packed;
+	int error;
+
+	/* add the loose object backend */
+	error = git_odb_backend_loose(&loose, objects_dir);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	error = add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	/* add the packed file backend */
+	error = git_odb_backend_pack(&packed, objects_dir);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	error = add_backend_internal(db, packed, GIT_PACKED_PRIORITY, as_alternates);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	return GIT_SUCCESS;
+}
+
+static int load_alternates(git_odb *odb, const char *objects_dir)
+{
+	char alternates_path[GIT_PATH_MAX];
+	char alternate[GIT_PATH_MAX];
+	char *buffer;
+
+	gitfo_buf alternates_buf = GITFO_BUF_INIT;
+	int error;
+
+	git__joinpath(alternates_path, objects_dir, GIT_ALTERNATES_FILE);
+
+	if (gitfo_exists(alternates_path) < GIT_SUCCESS)
+		return GIT_SUCCESS;
+
+	if (gitfo_read_file(&alternates_buf, alternates_path) < GIT_SUCCESS)
+		return GIT_EOSERR;
+
+	buffer = (char *)alternates_buf.data;
+	error = GIT_SUCCESS;
+
+	/* add each alternate as a new backend; one alternate per line */
+	while ((error == GIT_SUCCESS) && (buffer = git__strtok(alternate, buffer, "\r\n")) != NULL)
+		error = add_default_backends(odb, alternate, 1);
+
+	gitfo_free_buf(&alternates_buf);
+	return error;
+}
+
+int git_odb_open(git_odb **out, const char *objects_dir)
+{
+	git_odb *db;
+	int error;
+
+	assert(out && objects_dir);
+
+	*out = NULL;
+
+	if ((error = git_odb_new(&db)) < 0)
+		return error;
+
+	if ((error = add_default_backends(db, objects_dir, 0)) < GIT_SUCCESS)
+		goto cleanup;
+
+	if ((error = load_alternates(db, objects_dir)) < GIT_SUCCESS)
+		goto cleanup;
+
+	*out = db;
+	return GIT_SUCCESS;
+
+cleanup:
+	git_odb_close(db);
+	return error;
+}
+
+void git_odb_close(git_odb *db)
+{
+	unsigned int i;
+
+	if (db == NULL)
+		return;
+
+	for (i = 0; i < db->backends.length; ++i) {
+		backend_internal *internal = git_vector_get(&db->backends, i);
+		git_odb_backend *backend = internal->backend;
+
+		if (backend->free) backend->free(backend);
+		else free(backend);
+
+		free(internal);
+	}
+
+	git_vector_free(&db->backends);
+	free(db);
+}
+
+int git_odb_exists(git_odb *db, const git_oid *id)
+{
+	unsigned int i;
+	int found = 0;
+
+	assert(db && id);
+
+	for (i = 0; i < db->backends.length && !found; ++i) {
+		backend_internal *internal = git_vector_get(&db->backends, i);
+		git_odb_backend *b = internal->backend;
+
+		if (b->exists != NULL)
+			found = b->exists(b, id);
+	}
+
+	return found;
+}
+
+int git_odb_read_header(git_rawobj *out, git_odb *db, const git_oid *id)
+{
+	unsigned int i;
+	int error = GIT_ENOTFOUND;
+
+	assert(out && db && id);
+
+	for (i = 0; i < db->backends.length && error < 0; ++i) {
+		backend_internal *internal = git_vector_get(&db->backends, i);
+		git_odb_backend *b = internal->backend;
+
+		if (b->read_header != NULL)
+			error = b->read_header(out, b, id);
+	}
+
+	/*
+	 * no backend could read only the header.
+	 * try reading the whole object and freeing the contents
+	 */
+	if (error < 0) {
+		error = git_odb_read(out, db, id);
+		git_rawobj_close(out);
+	}
+
+	return error;
+}
+
+int git_odb_read(git_rawobj *out, git_odb *db, const git_oid *id)
+{
+	unsigned int i;
+	int error = GIT_ENOTFOUND;
+
+	assert(out && db && id);
+
+	for (i = 0; i < db->backends.length && error < 0; ++i) {
+		backend_internal *internal = git_vector_get(&db->backends, i);
+		git_odb_backend *b = internal->backend;
+
+		if (b->read != NULL)
+			error = b->read(out, b, id);
+	}
+
+	return error;
+}
+
+int git_odb_write(git_oid *id, git_odb *db, git_rawobj *obj)
+{
+	unsigned int i;
+	int error = GIT_ERROR;
+
+	assert(obj && db && id);
+
+	for (i = 0; i < db->backends.length && error < 0; ++i) {
+		backend_internal *internal = git_vector_get(&db->backends, i);
+		git_odb_backend *b = internal->backend;
+
+		/* we don't write in alternates! */
+		if (internal->is_alternate)
+			continue;
+
+		if (b->write != NULL)
+			error = b->write(id, b, obj);
+	}
+
+	return error;
+}
+
diff --git a/libgit2/src/odb.h b/libgit2/src/odb.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/odb.h
@@ -0,0 +1,17 @@
+#ifndef INCLUDE_odb_h__
+#define INCLUDE_odb_h__
+
+#include "git2/odb.h"
+#include "git2/oid.h"
+
+#include "vector.h"
+
+struct git_odb {
+	void *_internal;
+	git_vector backends;
+};
+
+int git_odb__hash_obj(git_oid *id, char *hdr, size_t n, int *len, git_rawobj *obj);
+int git_odb__inflate_buffer(void *in, size_t inlen, void *out, size_t outlen);
+
+#endif
diff --git a/libgit2/src/odb_loose.c b/libgit2/src/odb_loose.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/odb_loose.c
@@ -0,0 +1,658 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "git2/zlib.h"
+#include "git2/object.h"
+#include "fileops.h"
+#include "hash.h"
+#include "odb.h"
+#include "delta-apply.h"
+
+#include "git2/odb_backend.h"
+
+typedef struct {  /* object header data */
+	git_otype type;  /* object type */
+	size_t    size;  /* object size */
+} obj_hdr;
+
+typedef struct loose_backend {
+	git_odb_backend parent;
+
+	int object_zlib_level; /** loose object zlib compression level. */
+	int fsync_object_files; /** loose object file fsync flag. */
+	char *objects_dir;
+} loose_backend;
+
+
+/***********************************************************
+ *
+ * MISCELANEOUS HELPER FUNCTIONS
+ *
+ ***********************************************************/
+
+static int make_temp_file(git_file *fd, char *tmp, size_t n, char *file)
+{
+	char *template = "/tmp_obj_XXXXXX";
+	size_t tmplen = strlen(template);
+	int dirlen;
+
+	if ((dirlen = git__dirname_r(tmp, n, file)) < 0)
+		return GIT_ERROR;
+
+	if ((dirlen + tmplen) >= n)
+		return GIT_ERROR;
+
+	strcpy(tmp + dirlen, (dirlen) ? template : template + 1);
+
+	*fd = gitfo_mkstemp(tmp);
+	if (*fd < 0 && dirlen) {
+		/* create directory if it doesn't exist */
+		tmp[dirlen] = '\0';
+		if ((gitfo_exists(tmp) < 0) && gitfo_mkdir(tmp, 0755))
+			return GIT_ERROR;
+		/* try again */
+		strcpy(tmp + dirlen, template);
+		*fd = gitfo_mkstemp(tmp);
+	}
+	if (*fd < 0)
+		return GIT_ERROR;
+
+	return GIT_SUCCESS;
+}
+
+
+
+static size_t object_file_name(char *name, size_t n, char *dir, const git_oid *id)
+{
+	size_t len = strlen(dir);
+
+	/* check length: 43 = 40 hex sha1 chars + 2 * '/' + '\0' */
+	if (len+43 > n)
+		return len+43;
+
+	/* the object dir: eg $GIT_DIR/objects */
+	strcpy(name, dir);
+	if (name[len-1] != '/')
+		name[len++] = '/';
+
+	/* loose object filename: aa/aaa... (41 bytes) */
+	git_oid_pathfmt(&name[len], id);
+	name[len+41] = '\0';
+
+	return 0;
+}
+
+
+static size_t get_binary_object_header(obj_hdr *hdr, gitfo_buf *obj)
+{
+	unsigned char c;
+	unsigned char *data = obj->data;
+	size_t shift, size, used = 0;
+
+	if (obj->len == 0)
+		return 0;
+
+	c = data[used++];
+	hdr->type = (c >> 4) & 7;
+
+	size = c & 15;
+	shift = 4;
+	while (c & 0x80) {
+		if (obj->len <= used)
+			return 0;
+		if (sizeof(size_t) * 8 <= shift)
+			return 0;
+		c = data[used++];
+		size += (c & 0x7f) << shift;
+		shift += 7;
+	}
+	hdr->size = size;
+
+	return used;
+}
+
+static size_t get_object_header(obj_hdr *hdr, unsigned char *data)
+{
+	char c, typename[10];
+	size_t size, used = 0;
+
+	/*
+	 * type name string followed by space.
+	 */
+	while ((c = data[used]) != ' ') {
+		typename[used++] = c;
+		if (used >= sizeof(typename))
+			return 0;
+	}
+	typename[used] = 0;
+	if (used == 0)
+		return 0;
+	hdr->type = git_object_string2type(typename);
+	used++;  /* consume the space */
+
+	/*
+	 * length follows immediately in decimal (without
+	 * leading zeros).
+	 */
+	size = data[used++] - '0';
+	if (size > 9)
+		return 0;
+	if (size) {
+		while ((c = data[used]) != '\0') {
+			size_t d = c - '0';
+			if (d > 9)
+				break;
+			used++;
+			size = size * 10 + d;
+		}
+	}
+	hdr->size = size;
+
+	/*
+	 * the length must be followed by a zero byte
+	 */
+	if (data[used++] != '\0')
+		return 0;
+
+	return used;
+}
+
+
+
+/***********************************************************
+ *
+ * ZLIB RELATED FUNCTIONS
+ *
+ ***********************************************************/
+
+static void init_stream(z_stream *s, void *out, size_t len)
+{
+	memset(s, 0, sizeof(*s));
+	s->next_out  = out;
+	s->avail_out = len;
+}
+
+static void set_stream_input(z_stream *s, void *in, size_t len)
+{
+	s->next_in  = in;
+	s->avail_in = len;
+}
+
+static void set_stream_output(z_stream *s, void *out, size_t len)
+{
+	s->next_out  = out;
+	s->avail_out = len;
+}
+
+
+static int start_inflate(z_stream *s, gitfo_buf *obj, void *out, size_t len)
+{
+	int status;
+
+	init_stream(s, out, len);
+	set_stream_input(s, obj->data, obj->len);
+
+	if ((status = inflateInit(s)) < Z_OK)
+		return status;
+
+	return inflate(s, 0);
+}
+
+static int finish_inflate(z_stream *s)
+{
+	int status = Z_OK;
+
+	while (status == Z_OK)
+		status = inflate(s, Z_FINISH);
+
+	inflateEnd(s);
+
+	if ((status != Z_STREAM_END) || (s->avail_in != 0))
+		return GIT_ERROR;
+
+	return GIT_SUCCESS;
+}
+
+static int deflate_buf(z_stream *s, void *in, size_t len, int flush)
+{
+	int status = Z_OK;
+
+	set_stream_input(s, in, len);
+	while (status == Z_OK) {
+		status = deflate(s, flush);
+		if (s->avail_in == 0)
+			break;
+	}
+	return status;
+}
+
+static int deflate_obj(gitfo_buf *buf, char *hdr, int hdrlen, git_rawobj *obj, int level)
+{
+	z_stream zs;
+	int status;
+	size_t size;
+
+	assert(buf && !buf->data && hdr && obj);
+	assert(level == Z_DEFAULT_COMPRESSION || (level >= 0 && level <= 9));
+
+	buf->data = NULL;
+	buf->len  = 0;
+	init_stream(&zs, NULL, 0);
+
+	if (deflateInit(&zs, level) < Z_OK)
+		return GIT_ERROR;
+
+	size = deflateBound(&zs, hdrlen + obj->len);
+
+	if ((buf->data = git__malloc(size)) == NULL) {
+		deflateEnd(&zs);
+		return GIT_ERROR;
+	}
+
+	set_stream_output(&zs, buf->data, size);
+
+	/* compress the header */
+	status = deflate_buf(&zs, hdr, hdrlen, Z_NO_FLUSH);
+
+	/* if header compressed OK, compress the object */
+	if (status == Z_OK)
+		status = deflate_buf(&zs, obj->data, obj->len, Z_FINISH);
+
+	if (status != Z_STREAM_END) {
+		deflateEnd(&zs);
+		free(buf->data);
+		buf->data = NULL;
+		return GIT_ERROR;
+	}
+
+	buf->len = zs.total_out;
+	deflateEnd(&zs);
+
+	return GIT_SUCCESS;
+}
+
+static int is_zlib_compressed_data(unsigned char *data)
+{
+	unsigned int w;
+
+	w = ((unsigned int)(data[0]) << 8) + data[1];
+	return data[0] == 0x78 && !(w % 31);
+}
+
+static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
+{
+	unsigned char *buf, *head = hb;
+	size_t tail;
+
+	/*
+	 * allocate a buffer to hold the inflated data and copy the
+	 * initial sequence of inflated data from the tail of the
+	 * head buffer, if any.
+	 */
+	if ((buf = git__malloc(hdr->size + 1)) == NULL) {
+		inflateEnd(s);
+		return NULL;
+	}
+	tail = s->total_out - used;
+	if (used > 0 && tail > 0) {
+		if (tail > hdr->size)
+			tail = hdr->size;
+		memcpy(buf, head + used, tail);
+	}
+	used = tail;
+
+	/*
+	 * inflate the remainder of the object data, if any
+	 */
+	if (hdr->size < used)
+		inflateEnd(s);
+	else {
+		set_stream_output(s, buf + used, hdr->size - used);
+		if (finish_inflate(s)) {
+			free(buf);
+			return NULL;
+		}
+	}
+
+	return buf;
+}
+
+/*
+ * At one point, there was a loose object format that was intended to
+ * mimic the format used in pack-files. This was to allow easy copying
+ * of loose object data into packs. This format is no longer used, but
+ * we must still read it.
+ */
+static int inflate_packlike_loose_disk_obj(git_rawobj *out, gitfo_buf *obj)
+{
+	unsigned char *in, *buf;
+	obj_hdr hdr;
+	size_t len, used;
+
+	/*
+	 * read the object header, which is an (uncompressed)
+	 * binary encoding of the object type and size.
+	 */
+	if ((used = get_binary_object_header(&hdr, obj)) == 0)
+		return GIT_ERROR;
+
+	if (!git_object_typeisloose(hdr.type))
+		return GIT_ERROR;
+
+	/*
+	 * allocate a buffer and inflate the data into it
+	 */
+	buf = git__malloc(hdr.size + 1);
+	if (!buf)
+		return GIT_ERROR;
+
+	in  = ((unsigned char *)obj->data) + used;
+	len = obj->len - used;
+	if (git_odb__inflate_buffer(in, len, buf, hdr.size)) {
+		free(buf);
+		return GIT_ERROR;
+	}
+	buf[hdr.size] = '\0';
+
+	out->data = buf;
+	out->len  = hdr.size;
+	out->type = hdr.type;
+
+	return GIT_SUCCESS;
+}
+
+static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
+{
+	unsigned char head[64], *buf;
+	z_stream zs;
+	int z_status;
+	obj_hdr hdr;
+	size_t used;
+
+	/*
+	 * check for a pack-like loose object
+	 */
+	if (!is_zlib_compressed_data(obj->data))
+		return inflate_packlike_loose_disk_obj(out, obj);
+
+	/*
+	 * inflate the initial part of the io buffer in order
+	 * to parse the object header (type and size).
+	 */
+	if ((z_status = start_inflate(&zs, obj, head, sizeof(head))) < Z_OK)
+		return GIT_ERROR;
+
+	if ((used = get_object_header(&hdr, head)) == 0)
+		return GIT_ERROR;
+
+	if (!git_object_typeisloose(hdr.type))
+		return GIT_ERROR;
+
+	/*
+	 * allocate a buffer and inflate the object data into it
+	 * (including the initial sequence in the head buffer).
+	 */
+	if ((buf = inflate_tail(&zs, head, used, &hdr)) == NULL)
+		return GIT_ERROR;
+	buf[hdr.size] = '\0';
+
+	out->data = buf;
+	out->len  = hdr.size;
+	out->type = hdr.type;
+
+	return GIT_SUCCESS;
+}
+
+
+
+
+
+
+/***********************************************************
+ *
+ * ODB OBJECT READING & WRITING
+ *
+ * Backend for the public API; read headers and full objects
+ * from the ODB. Write raw data to the ODB.
+ *
+ ***********************************************************/
+
+static int read_loose(git_rawobj *out, const char *loc)
+{
+	int error;
+	gitfo_buf obj = GITFO_BUF_INIT;
+
+	assert(out && loc);
+
+	out->data = NULL;
+	out->len  = 0;
+	out->type = GIT_OBJ_BAD;
+
+	if (gitfo_read_file(&obj, loc) < 0)
+		return GIT_ENOTFOUND;
+
+	error = inflate_disk_obj(out, &obj);
+	gitfo_free_buf(&obj);
+
+	return error;
+}
+
+static int read_header_loose(git_rawobj *out, const char *loc)
+{
+	int error = GIT_SUCCESS, z_return = Z_ERRNO, read_bytes;
+	git_file fd;
+	z_stream zs;
+	obj_hdr header_obj;
+	unsigned char raw_buffer[16], inflated_buffer[64];
+
+	assert(out && loc);
+
+	out->data = NULL;
+
+	if ((fd = gitfo_open(loc, O_RDONLY)) < 0)
+		return GIT_ENOTFOUND;
+
+	init_stream(&zs, inflated_buffer, sizeof(inflated_buffer));
+
+	if (inflateInit(&zs) < Z_OK) {
+		error = GIT_EZLIB;
+		goto cleanup;
+	}
+
+	do {
+		if ((read_bytes = read(fd, raw_buffer, sizeof(raw_buffer))) > 0) {
+			set_stream_input(&zs, raw_buffer, read_bytes);
+			z_return = inflate(&zs, 0);
+		}
+	} while (z_return == Z_OK);
+
+	if ((z_return != Z_STREAM_END && z_return != Z_BUF_ERROR)
+		|| get_object_header(&header_obj, inflated_buffer) == 0
+		|| git_object_typeisloose(header_obj.type) == 0) {
+		error = GIT_EOBJCORRUPTED;
+		goto cleanup;
+	}
+
+	out->len  = header_obj.size;
+	out->type = header_obj.type;
+
+cleanup:
+	finish_inflate(&zs);
+	gitfo_close(fd);
+	return error;
+}
+
+static int write_obj(gitfo_buf *buf, git_oid *id, loose_backend *backend)
+{
+	char file[GIT_PATH_MAX];
+	char temp[GIT_PATH_MAX];
+	git_file fd;
+
+	if (object_file_name(file, sizeof(file), backend->objects_dir, id))
+		return GIT_EOSERR;
+
+	if (make_temp_file(&fd, temp, sizeof(temp), file) < 0)
+		return GIT_EOSERR;
+
+	if (gitfo_write(fd, buf->data, buf->len) < 0) {
+		gitfo_close(fd);
+		gitfo_unlink(temp);
+		return GIT_EOSERR;
+	}
+
+	if (backend->fsync_object_files)
+		gitfo_fsync(fd);
+	gitfo_close(fd);
+	gitfo_chmod(temp, 0444);
+
+	if (gitfo_mv(temp, file) < 0) {
+		gitfo_unlink(temp);
+		return GIT_EOSERR;
+	}
+
+	return GIT_SUCCESS;
+}
+
+static int locate_object(char *object_location, loose_backend *backend, const git_oid *oid)
+{
+	object_file_name(object_location, GIT_PATH_MAX, backend->objects_dir, oid);
+	return gitfo_exists(object_location);
+}
+
+
+
+
+
+
+
+
+
+/***********************************************************
+ *
+ * LOOSE BACKEND PUBLIC API
+ *
+ * Implement the git_odb_backend API calls
+ *
+ ***********************************************************/
+
+int loose_backend__read_header(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
+{
+	char object_path[GIT_PATH_MAX];
+
+	assert(obj && backend && oid);
+
+	if (locate_object(object_path, (loose_backend *)backend, oid) < 0)
+		return GIT_ENOTFOUND;
+
+	return read_header_loose(obj, object_path);
+}
+
+
+int loose_backend__read(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
+{
+	char object_path[GIT_PATH_MAX];
+
+	assert(obj && backend && oid);
+
+	if (locate_object(object_path, (loose_backend *)backend, oid) < 0)
+		return GIT_ENOTFOUND;
+
+	return read_loose(obj, object_path);
+}
+
+int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
+{
+	char object_path[GIT_PATH_MAX];
+
+	assert(backend && oid);
+
+	return locate_object(object_path, (loose_backend *)backend, oid) == GIT_SUCCESS;
+}
+
+
+int loose_backend__write(git_oid *id, git_odb_backend *_backend, git_rawobj *obj)
+{
+	char hdr[64];
+	int  hdrlen;
+	gitfo_buf buf = GITFO_BUF_INIT;
+	int error;
+	loose_backend *backend;
+
+	assert(id && _backend && obj);
+
+	backend = (loose_backend *)_backend;
+
+	if ((error = git_odb__hash_obj(id, hdr, sizeof(hdr), &hdrlen, obj)) < 0)
+		return error;
+
+	if (git_odb_exists(_backend->odb, id))
+		return GIT_SUCCESS;
+
+	if ((error = deflate_obj(&buf, hdr, hdrlen, obj, backend->object_zlib_level)) < 0)
+		return error;
+
+	error = write_obj(&buf, id, backend);
+
+	gitfo_free_buf(&buf);
+	return error;
+}
+
+void loose_backend__free(git_odb_backend *_backend)
+{
+	loose_backend *backend;
+	assert(_backend);
+	backend = (loose_backend *)_backend;
+
+	free(backend->objects_dir);
+	free(backend);
+}
+
+int git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir)
+{
+	loose_backend *backend;
+
+	backend = git__calloc(1, sizeof(loose_backend));
+	if (backend == NULL)
+		return GIT_ENOMEM;
+
+	backend->objects_dir = git__strdup(objects_dir);
+	if (backend->objects_dir == NULL) {
+		free(backend);
+		return GIT_ENOMEM;
+	}
+
+	backend->object_zlib_level = Z_BEST_SPEED;
+	backend->fsync_object_files = 0;
+
+	backend->parent.read = &loose_backend__read;
+	backend->parent.read_header = &loose_backend__read_header;
+	backend->parent.write = &loose_backend__write;
+	backend->parent.exists = &loose_backend__exists;
+	backend->parent.free = &loose_backend__free;
+
+	*backend_out = (git_odb_backend *)backend;
+	return GIT_SUCCESS;
+}
diff --git a/libgit2/src/odb_pack.c b/libgit2/src/odb_pack.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/odb_pack.c
@@ -0,0 +1,1406 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "git2/zlib.h"
+#include "git2/repository.h"
+#include "fileops.h"
+#include "hash.h"
+#include "odb.h"
+#include "delta-apply.h"
+
+#include "git2/odb_backend.h"
+
+#define DEFAULT_WINDOW_SIZE \
+	(sizeof(void*) >= 8 \
+		?  1 * 1024 * 1024 * 1024 \
+		: 32 * 1024 * 1024)
+
+#define DEFAULT_MAPPED_LIMIT \
+	((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256))
+
+#define PACK_SIGNATURE 0x5041434b	/* "PACK" */
+#define PACK_VERSION 2
+#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3))
+struct pack_header {
+	uint32_t hdr_signature;
+	uint32_t hdr_version;
+	uint32_t hdr_entries;
+};
+
+/*
+ * The first four bytes of index formats later than version 1 should
+ * start with this signature, as all older git binaries would find this
+ * value illegal and abort reading the file.
+ *
+ * This is the case because the number of objects in a packfile
+ * cannot exceed 1,431,660,000 as every object would need at least
+ * 3 bytes of data and the overall packfile cannot exceed 4 GiB with
+ * version 1 of the index file due to the offsets limited to 32 bits.
+ * Clearly the signature exceeds this maximum.
+ *
+ * Very old git binaries will also compare the first 4 bytes to the
+ * next 4 bytes in the index and abort with a "non-monotonic index"
+ * error if the second 4 byte word is smaller than the first 4
+ * byte word.  This would be true in the proposed future index
+ * format as idx_signature would be greater than idx_version.
+ */
+#define PACK_IDX_SIGNATURE 0xff744f63	/* "\377tOc" */
+
+struct pack_idx_header {
+	uint32_t idx_signature;
+	uint32_t idx_version;
+};
+
+struct pack_window {
+	struct pack_window *next;
+	git_map window_map;
+	off_t offset;
+	unsigned int last_used;
+	unsigned int inuse_cnt;
+};
+
+struct pack_file {
+	struct pack_window *windows;
+	off_t pack_size;
+
+	git_map index_map;
+
+	uint32_t num_objects;
+	uint32_t num_bad_objects;
+	git_oid *bad_object_sha1; /* array of git_oid */
+
+	int index_version;
+	time_t mtime;
+	int pack_fd;
+	unsigned pack_local:1, pack_keep:1;
+	git_oid sha1;
+
+	/* something like ".git/objects/pack/xxxxx.pack" */
+	char pack_name[GIT_FLEX_ARRAY]; /* more */
+};
+
+struct pack_entry {
+	off_t offset;
+	git_oid sha1;
+	struct pack_file *p;
+};
+
+struct pack__dirent {
+	struct pack_backend *backend;
+	int is_pack_local;
+};
+
+struct pack_backend {
+	git_odb_backend parent;
+	git_vector packs;
+	struct pack_file *last_found;
+
+	size_t window_size; /* needs default value */
+
+	size_t mapped_limit; /* needs default value */
+	size_t peak_mapped;
+	size_t mapped;
+
+	size_t used_ctr;
+
+	unsigned int peak_open_windows;
+	unsigned int open_windows;
+
+	unsigned int mmap_calls;
+};
+
+/**
+ * The wonderful tale of a Packed Object lookup query
+ * ===================================================
+ *   A riveting and epic story of epicness and ASCII
+ *          art, presented by yours truly,
+ *               Sir Vicent of Marti
+ *
+ *
+ *	Chapter 1: Once upon a time...
+ *	Initialization of the Pack Backend
+ *	--------------------------------------------------
+ *
+ *	# git_odb_backend_pack
+ *	| Creates the pack backend structure, initializes the
+ *	| callback pointers to our default read() and exist() methods,
+ *	| and tries to preload all the known packfiles in the ODB.
+ *  |
+ *	|-# packfile_load_all
+ *	  | Tries to find the `pack` folder, if it exists. ODBs without
+ *	  | a pack folder are ignored altogether. If there's a `pack` folder
+ *	  | we run a `dirent` callback through every file in the pack folder
+ *	  | to find our packfiles. The packfiles are then sorted according
+ *	  | to a sorting callback.
+ * 	  |
+ *	  |-# packfile_load__cb
+ *	  | | This callback is called from `dirent` with every single file
+ *	  | | inside the pack folder. We find the packs by actually locating
+ *	  | | their index (ends in ".idx"). From that index, we verify that
+ *	  | | the corresponding packfile exists and is valid, and if so, we
+ *    | | add it to the pack list.
+ *	  | |
+ *	  | |-# packfile_check
+ *	  |     Make sure that there's a packfile to back this index, and store
+ *	  |     some very basic information regarding the packfile itself,
+ *	  |     such as the full path, the size, and the modification time.
+ *	  |     We don't actually open the packfile to check for internal consistency.
+ *    |
+ *    |-# packfile_sort__cb
+ *        Sort all the preloaded packs according to some specific criteria:
+ *        we prioritize the "newer" packs because it's more likely they
+ *        contain the objects we are looking for, and we prioritize local
+ *        packs over remote ones.
+ *
+ *
+ *
+ *	Chapter 2: To be, or not to be...
+ *	A standard packed `exist` query for an OID
+ *	--------------------------------------------------
+ *
+ *  # pack_backend__exists
+ *  | Check if the given SHA1 oid exists in any of the packs
+ *  | that have been loaded for our ODB.
+ *  |
+ *  |-# pack_entry_find
+ *    | Iterate through all the packs that have been preloaded
+ *    | (starting by the pack where the latest object was found)
+ *    | to try to find the OID in one of them.
+ *    |
+ *    |-# pack_entry_find1
+ *      | Check the index of an individual pack to see if the SHA1
+ *      | OID can be found. If we can find the offset to that SHA1
+ *      | inside of the index, that means the object is contained
+ *      | inside of the packfile and we can stop searching.
+ *      | Before returning, we verify that the packfile behing the
+ *      | index we are searching still exists on disk.
+ *      |
+ *      |-# pack_entry_find_offset
+ *      | | Mmap the actual index file to disk if it hasn't been opened
+ *      | | yet, and run a binary search through it to find the OID.
+ *      | | See <http://book.git-scm.com/7_the_packfile.html> for specifics
+ *      | | on the Packfile Index format and how do we find entries in it.
+ *      | |
+ *      | |-# pack_index_open
+ *      |   | Guess the name of the index based on the full path to the
+ *      |   | packfile, open it and verify its contents. Only if the index
+ *      |   | has not been opened already.
+ *      |   |
+ *      |   |-# pack_index_check
+ *      |       Mmap the index file and do a quick run through the header
+ *      |       to guess the index version (right now we support v1 and v2),
+ *      |       and to verify that the size of the index makes sense.
+ *      |
+ *      |-# packfile_open
+ *          See `packfile_open` in Chapter 3
+ *
+ *
+ *
+ *	Chapter 3: The neverending story...
+ *	A standard packed `lookup` query for an OID
+ *	--------------------------------------------------
+ *	TODO
+ *
+ */
+
+
+
+ 
+/***********************************************************
+ *
+ * FORWARD DECLARATIONS
+ *
+ ***********************************************************/
+
+static void pack_window_free_all(struct pack_backend *backend, struct pack_file *p);
+static int pack_window_contains(struct pack_window *win, off_t offset);
+
+static void pack_window_scan_lru(struct pack_file *p, struct pack_file **lru_p,
+		struct pack_window **lru_w, struct pack_window **lru_l);
+
+static int pack_window_close_lru( struct pack_backend *backend,
+		struct pack_file *current, git_file keep_fd);
+
+static void pack_window_close(struct pack_window **w_cursor);
+
+static unsigned char *pack_window_open( struct pack_backend *backend,
+		struct pack_file *p, struct pack_window **w_cursor, off_t offset,
+		unsigned int *left);
+
+static int packfile_sort__cb(const void *a_, const void *b_);
+
+static void pack_index_free(struct pack_file *p);
+
+static int pack_index_check(const char *path,  struct pack_file *p);
+static int pack_index_open(struct pack_file *p);
+
+static struct pack_file *packfile_alloc(int extra);
+static int packfile_open(struct pack_file *p);
+static int packfile_check(struct pack_file **pack_out, const char *path, int local);
+static int packfile_load__cb(void *_data, char *path);
+static int packfile_load_all(struct pack_backend *backend, const char *odb_path, int local);
+
+static off_t nth_packed_object_offset(const struct pack_file *p, uint32_t n);
+
+static int pack_entry_find_offset(off_t *offset_out,
+		struct pack_file *p, const git_oid *oid);
+
+static int pack_entry_find1(struct pack_entry *e,
+		struct pack_file *p, const git_oid *oid);
+
+static int pack_entry_find(struct pack_entry *e,
+		struct pack_backend *backend, const git_oid *oid);
+
+static off_t get_delta_base(struct pack_backend *backend,
+		struct pack_file *p, struct pack_window **w_curs,
+		off_t *curpos, git_otype type,
+		off_t delta_obj_offset);
+
+static unsigned long packfile_unpack_header1(
+		size_t *sizep,
+		git_otype *type, 
+		const unsigned char *buf,
+		unsigned long len);
+
+static int packfile_unpack_header(
+		size_t *size_p,
+		git_otype *type_p,
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_curs,
+		off_t *curpos);
+
+static int packfile_unpack_compressed(
+		git_rawobj *obj,
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_curs,
+		off_t curpos,
+		size_t size,
+		git_otype type);
+
+static int packfile_unpack_delta(
+		git_rawobj *obj,
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_curs,
+		off_t curpos,
+		size_t delta_size,
+		git_otype delta_type,
+		off_t obj_offset);
+
+static int packfile_unpack(git_rawobj *obj, struct pack_backend *backend,
+		struct pack_file *p, off_t obj_offset);
+
+
+
+
+
+/***********************************************************
+ *
+ * PACK WINDOW MANAGEMENT
+ *
+ ***********************************************************/
+
+void pack_window_free_all(struct pack_backend *backend, struct pack_file *p)
+{
+	while (p->windows) {
+		struct pack_window *w = p->windows;
+		assert(w->inuse_cnt == 0);
+
+		backend->mapped -= w->window_map.len;
+		backend->open_windows--;
+
+		gitfo_free_map(&w->window_map);
+
+		p->windows = w->next;
+		free(w);
+	}
+}
+
+GIT_INLINE(int) pack_window_contains(struct pack_window *win, off_t offset)
+{
+	/* We must promise at least 20 bytes (one hash) after the
+	 * offset is available from this window, otherwise the offset
+	 * is not actually in this window and a different window (which
+	 * has that one hash excess) must be used.  This is to support
+	 * the object header and delta base parsing routines below.
+	 */
+	off_t win_off = win->offset;
+	return win_off <= offset
+		&& (offset + 20) <= (off_t)(win_off + win->window_map.len);
+}
+
+static void pack_window_scan_lru(
+	struct pack_file *p,
+	struct pack_file **lru_p,
+	struct pack_window **lru_w,
+	struct pack_window **lru_l)
+{
+	struct pack_window *w, *w_l;
+
+	for (w_l = NULL, w = p->windows; w; w = w->next) {
+		if (!w->inuse_cnt) {
+			if (!*lru_w || w->last_used < (*lru_w)->last_used) {
+				*lru_p = p;
+				*lru_w = w;
+				*lru_l = w_l;
+			}
+		}
+		w_l = w;
+	}
+}
+
+static int pack_window_close_lru(
+		struct pack_backend *backend,
+		struct pack_file *current,
+		git_file keep_fd)
+{
+	struct pack_file *lru_p = NULL;
+	struct pack_window *lru_w = NULL, *lru_l = NULL;
+	size_t i;
+
+	if (current)
+		pack_window_scan_lru(current, &lru_p, &lru_w, &lru_l);
+
+	for (i = 0; i < backend->packs.length; ++i)
+		pack_window_scan_lru(git_vector_get(&backend->packs, i), &lru_p, &lru_w, &lru_l);
+
+	if (lru_p) {
+		backend->mapped -= lru_w->window_map.len;
+		gitfo_free_map(&lru_w->window_map);
+
+		if (lru_l)
+			lru_l->next = lru_w->next;
+		else {
+			lru_p->windows = lru_w->next;
+			if (!lru_p->windows && lru_p->pack_fd != keep_fd) {
+				gitfo_close(lru_p->pack_fd);
+				lru_p->pack_fd = -1;
+			}
+		}
+
+		free(lru_w);
+		backend->open_windows--;
+		return GIT_SUCCESS;
+	}
+
+	return GIT_ERROR;
+}
+
+static void pack_window_close(struct pack_window **w_cursor)
+{
+	struct pack_window *w = *w_cursor;
+	if (w) {
+		w->inuse_cnt--;
+		*w_cursor = NULL;
+	}
+}
+
+static unsigned char *pack_window_open(
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_cursor,
+		off_t offset,
+		unsigned int *left)
+{
+	struct pack_window *win = *w_cursor;
+
+	if (p->pack_fd == -1 && packfile_open(p) < GIT_SUCCESS)
+		return NULL;
+
+	/* Since packfiles end in a hash of their content and it's
+	 * pointless to ask for an offset into the middle of that
+	 * hash, and the pack_window_contains function above wouldn't match
+	 * don't allow an offset too close to the end of the file.
+	 */
+	if (offset > (p->pack_size - 20))
+		return NULL;
+
+	if (!win || !pack_window_contains(win, offset)) {
+
+		if (win)
+			win->inuse_cnt--;
+
+		for (win = p->windows; win; win = win->next) {
+			if (pack_window_contains(win, offset))
+				break;
+		}
+
+		if (!win) {
+			size_t window_align = backend->window_size / 2;
+			size_t len;
+
+			win = git__calloc(1, sizeof(*win));
+			win->offset = (offset / window_align) * window_align;
+
+			len = (size_t)(p->pack_size - win->offset);
+			if (len > backend->window_size)
+				len = backend->window_size;
+
+			backend->mapped += len;
+
+			while (backend->mapped_limit < backend->mapped &&
+				pack_window_close_lru(backend, p, p->pack_fd) == GIT_SUCCESS) {}
+
+			if (gitfo_map_ro(&win->window_map, p->pack_fd,
+					win->offset, len) < GIT_SUCCESS)
+				return NULL;
+
+			backend->mmap_calls++;
+			backend->open_windows++;
+
+			if (backend->mapped > backend->peak_mapped)
+				backend->peak_mapped = backend->mapped;
+
+			if (backend->open_windows > backend->peak_open_windows)
+				backend->peak_open_windows = backend->open_windows;
+
+			win->next = p->windows;
+			p->windows = win;
+		}
+	}
+
+	if (win != *w_cursor) {
+		win->last_used = backend->used_ctr++;
+		win->inuse_cnt++;
+		*w_cursor = win;
+	}
+
+	offset -= win->offset;
+	assert(git__is_sizet(offset));
+
+	if (left)
+		*left = win->window_map.len - (size_t)offset;
+
+	return (unsigned char *)win->window_map.data + offset;
+}
+
+
+
+
+
+
+
+/***********************************************************
+ *
+ * PACK INDEX METHODS
+ *
+ ***********************************************************/
+
+static void pack_index_free(struct pack_file *p)
+{
+	if (p->index_map.data) {
+		gitfo_free_map(&p->index_map);
+		p->index_map.data = NULL;
+	}
+}
+
+static int pack_index_check(const char *path,  struct pack_file *p)
+{
+	struct pack_idx_header *hdr;
+	uint32_t version, nr, i, *index;
+
+	void *idx_map;
+	size_t idx_size;
+
+	struct stat st;
+
+	/* TODO: properly open the file without access time */
+	git_file fd = gitfo_open(path, O_RDONLY /*| O_NOATIME */);
+
+	int error;
+
+	if (fd < 0)
+		return GIT_EOSERR;
+
+	if (gitfo_fstat(fd, &st) < GIT_SUCCESS) {
+		gitfo_close(fd);
+		return GIT_EOSERR;
+	}
+
+	if (!git__is_sizet(st.st_size))
+		return GIT_ENOMEM;
+
+	idx_size = (size_t)st.st_size;
+
+	if (idx_size < 4 * 256 + 20 + 20) {
+		gitfo_close(fd);
+		return GIT_EOBJCORRUPTED;
+	}
+
+	error = gitfo_map_ro(&p->index_map, fd, 0, idx_size);
+	gitfo_close(fd);
+
+	if (error < GIT_SUCCESS)
+		return error;
+
+	hdr = idx_map = p->index_map.data;
+
+	if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
+		version = ntohl(hdr->idx_version);
+
+		if (version < 2 || version > 2) {
+			gitfo_free_map(&p->index_map);
+			return GIT_EOBJCORRUPTED; /* unsupported index version */
+		}
+
+	} else
+		version = 1;
+
+	nr = 0;
+	index = idx_map;
+
+	if (version > 1)
+		index += 2;  /* skip index header */
+
+	for (i = 0; i < 256; i++) {
+		uint32_t n = ntohl(index[i]);
+		if (n < nr) {
+			gitfo_free_map(&p->index_map);
+			return GIT_EOBJCORRUPTED; /* non-monotonic index */
+		}
+		nr = n;
+	}
+
+	if (version == 1) {
+		/*
+		 * Total size:
+		 *  - 256 index entries 4 bytes each
+		 *  - 24-byte entries * nr (20-byte sha1 + 4-byte offset)
+		 *  - 20-byte SHA1 of the packfile
+		 *  - 20-byte SHA1 file checksum
+		 */
+		if (idx_size != 4*256 + nr * 24 + 20 + 20) {
+			gitfo_free_map(&p->index_map);
+			return GIT_EOBJCORRUPTED;
+		}
+	} else if (version == 2) {
+		/*
+		 * Minimum size:
+		 *  - 8 bytes of header
+		 *  - 256 index entries 4 bytes each
+		 *  - 20-byte sha1 entry * nr
+		 *  - 4-byte crc entry * nr
+		 *  - 4-byte offset entry * nr
+		 *  - 20-byte SHA1 of the packfile
+		 *  - 20-byte SHA1 file checksum
+		 * And after the 4-byte offset table might be a
+		 * variable sized table containing 8-byte entries
+		 * for offsets larger than 2^31.
+		 */
+		unsigned long min_size = 8 + 4*256 + nr*(20 + 4 + 4) + 20 + 20;
+		unsigned long max_size = min_size;
+
+		if (nr)
+			max_size += (nr - 1)*8;
+
+		if (idx_size < min_size || idx_size > max_size) {
+			gitfo_free_map(&p->index_map);
+			return GIT_EOBJCORRUPTED;
+		}
+
+		/* Make sure that off_t is big enough to access the whole pack...
+		 * Is this an issue in libgit2? It shouldn't. */
+		if (idx_size != min_size && (sizeof(off_t) <= 4)) {
+			gitfo_free_map(&p->index_map);
+			return GIT_EOSERR;
+		}
+	}
+
+	p->index_version = version;
+	p->num_objects = nr;
+	return GIT_SUCCESS;
+}
+
+static int pack_index_open(struct pack_file *p)
+{
+	char *idx_name;
+	int error;
+
+	if (p->index_map.data)
+		return GIT_SUCCESS;
+
+	idx_name = git__strdup(p->pack_name);
+	strcpy(idx_name + strlen(idx_name) - STRLEN(".pack"), ".idx");
+
+	error = pack_index_check(idx_name, p);
+	free(idx_name);
+
+	return error;
+}
+
+
+
+
+
+
+
+
+
+/***********************************************************
+ *
+ * PACKFILE METHODS
+ *
+ ***********************************************************/
+
+static int packfile_sort__cb(const void *a_, const void *b_)
+{
+	struct pack_file *a = *((struct pack_file **)a_);
+	struct pack_file *b = *((struct pack_file **)b_);
+	int st;
+
+	/*
+	 * Local packs tend to contain objects specific to our
+	 * variant of the project than remote ones.  In addition,
+	 * remote ones could be on a network mounted filesystem.
+	 * Favor local ones for these reasons.
+	 */
+	st = a->pack_local - b->pack_local;
+	if (st)
+		return -st;
+
+	/*
+	 * Younger packs tend to contain more recent objects,
+	 * and more recent objects tend to get accessed more
+	 * often.
+	 */
+	if (a->mtime < b->mtime)
+		return 1;
+	else if (a->mtime == b->mtime)
+		return 0;
+
+	return -1;
+}
+
+static struct pack_file *packfile_alloc(int extra)
+{
+	struct pack_file *p = git__malloc(sizeof(*p) + extra);
+	memset(p, 0, sizeof(*p));
+	p->pack_fd = -1;
+	return p;
+}
+
+
+static void packfile_free(struct pack_backend *backend, struct pack_file *p)
+{
+	assert(p);
+
+	/* clear_delta_base_cache(); */
+	pack_window_free_all(backend, p);
+
+	if (p->pack_fd != -1)
+		gitfo_close(p->pack_fd);
+
+	pack_index_free(p);
+
+	free(p->bad_object_sha1);
+	free(p);
+}
+
+static int packfile_open(struct pack_file *p)
+{
+	struct stat st;
+	struct pack_header hdr;
+	git_oid sha1;
+	unsigned char *idx_sha1;
+
+	if (!p->index_map.data && pack_index_open(p) < GIT_SUCCESS)
+		return GIT_ENOTFOUND;
+
+	/* TODO: open with noatime */
+	p->pack_fd = gitfo_open(p->pack_name, O_RDONLY);
+	if (p->pack_fd < 0 || gitfo_fstat(p->pack_fd, &st) < GIT_SUCCESS)
+		return GIT_EOSERR;
+
+	/* If we created the struct before we had the pack we lack size. */
+	if (!p->pack_size) {
+		if (!S_ISREG(st.st_mode))
+			goto cleanup;
+		p->pack_size = (off_t)st.st_size;
+	} else if (p->pack_size != st.st_size)
+		goto cleanup;
+
+#if 0
+	/* We leave these file descriptors open with sliding mmap;
+	 * there is no point keeping them open across exec(), though.
+	 */
+	fd_flag = fcntl(p->pack_fd, F_GETFD, 0);
+	if (fd_flag < 0)
+		return error("cannot determine file descriptor flags");
+
+	fd_flag |= FD_CLOEXEC;
+	if (fcntl(p->pack_fd, F_SETFD, fd_flag) == -1)
+		return GIT_EOSERR;
+#endif
+
+	/* Verify we recognize this pack file format. */
+	if (gitfo_read(p->pack_fd, &hdr, sizeof(hdr)) < GIT_SUCCESS)
+		goto cleanup;
+
+	if (hdr.hdr_signature != htonl(PACK_SIGNATURE))
+		goto cleanup;
+
+	if (!pack_version_ok(hdr.hdr_version))
+		goto cleanup;
+
+	/* Verify the pack matches its index. */
+	if (p->num_objects != ntohl(hdr.hdr_entries))
+		goto cleanup;
+
+	if (gitfo_lseek(p->pack_fd, p->pack_size - GIT_OID_RAWSZ, SEEK_SET) == -1)
+		goto cleanup;
+
+	if (gitfo_read(p->pack_fd, sha1.id, GIT_OID_RAWSZ) < GIT_SUCCESS)
+		goto cleanup;
+
+	idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
+
+	if (git_oid_cmp(&sha1, (git_oid *)idx_sha1) != 0)
+		goto cleanup;
+
+	return GIT_SUCCESS;	
+
+cleanup:
+	gitfo_close(p->pack_fd);
+	p->pack_fd = -1;
+	return GIT_EPACKCORRUPTED;
+}
+
+static int packfile_check(struct pack_file **pack_out, const char *path, int local)
+{
+	struct stat st;
+	struct pack_file *p;
+	size_t path_len;
+
+	*pack_out = NULL;
+	path_len = strlen(path);
+	p = packfile_alloc(path_len + 2);
+
+	/*
+	 * Make sure a corresponding .pack file exists and that
+	 * the index looks sane.
+	 */
+	path_len -= STRLEN(".idx");
+	if (path_len < 1) {
+		free(p);
+		return GIT_ENOTFOUND;
+	}
+
+	memcpy(p->pack_name, path, path_len);
+
+	strcpy(p->pack_name + path_len, ".keep");
+	if (gitfo_exists(p->pack_name) == GIT_SUCCESS)
+		p->pack_keep = 1;
+
+	strcpy(p->pack_name + path_len, ".pack");
+	if (gitfo_stat(p->pack_name, &st) < GIT_SUCCESS || !S_ISREG(st.st_mode)) {
+		free(p);
+		return GIT_ENOTFOUND;
+	}
+
+	/* ok, it looks sane as far as we can check without
+	 * actually mapping the pack file.
+	 */
+	p->pack_size = (off_t)st.st_size;
+	p->pack_local = local;
+	p->mtime = st.st_mtime;
+
+	/* see if we can parse the sha1 oid in the packfile name */
+	if (path_len < 40 ||
+		git_oid_mkstr(&p->sha1, path + path_len - GIT_OID_HEXSZ) < GIT_SUCCESS)
+		memset(&p->sha1, 0x0, GIT_OID_RAWSZ);
+
+	*pack_out = p;
+	return GIT_SUCCESS;
+}
+
+static int packfile_load__cb(void *_data, char *path)
+{
+	struct pack__dirent *data = (struct pack__dirent *)_data;
+	struct pack_file *pack;
+	int error;
+
+	if (git__suffixcmp(path, ".idx") != 0)
+		return GIT_SUCCESS; /* not an index */
+
+	/* FIXME: git.git checks for duplicate packs.
+	 * But that makes no fucking sense. Our dirent is not
+	 * going to generate dupicate entries */
+
+	error = packfile_check(&pack, path, data->is_pack_local);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	if (git_vector_insert(&data->backend->packs, pack) < GIT_SUCCESS) {
+		free(pack);
+		return GIT_ENOMEM;
+	}
+
+	return GIT_SUCCESS;
+}
+
+static int packfile_load_all(struct pack_backend *backend, const char *odb_path, int local)
+{
+	int error;
+	char path[GIT_PATH_MAX];
+	struct pack__dirent data;
+
+	data.backend = backend;
+	data.is_pack_local = local;
+
+	git__joinpath(path, odb_path, "pack");
+	if (gitfo_isdir(path) < GIT_SUCCESS)
+		return GIT_SUCCESS;
+
+	error = gitfo_dirent(path, GIT_PATH_MAX, packfile_load__cb, (void *)&data);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	git_vector_sort(&backend->packs);
+	backend->last_found = git_vector_get(&backend->packs, 0);
+
+	return GIT_SUCCESS;
+}
+
+
+
+
+
+
+
+
+/***********************************************************
+ *
+ * PACKFILE ENTRY SEARCH INTERNALS
+ *
+ ***********************************************************/
+
+static off_t nth_packed_object_offset(const struct pack_file *p, uint32_t n)
+{
+	const unsigned char *index = p->index_map.data;
+	index += 4 * 256;
+	if (p->index_version == 1) {
+		return ntohl(*((uint32_t *)(index + 24 * n)));
+	} else {
+		uint32_t off;
+		index += 8 + p->num_objects * (20 + 4);
+		off = ntohl(*((uint32_t *)(index + 4 * n)));
+		if (!(off & 0x80000000))
+			return off;
+		index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
+		return (((uint64_t)ntohl(*((uint32_t *)(index + 0)))) << 32) |
+				   ntohl(*((uint32_t *)(index + 4)));
+	}
+}
+
+static int pack_entry_find_offset(
+		off_t *offset_out,
+		struct pack_file *p,
+		const git_oid *oid)
+{
+	const uint32_t *level1_ofs = p->index_map.data;
+	const unsigned char *index = p->index_map.data;
+	unsigned hi, lo, stride;
+
+	*offset_out = 0;
+
+	if (index == NULL) {
+		int error;
+
+		if ((error = pack_index_open(p)) < GIT_SUCCESS)
+			return error;
+
+		assert(p->index_map.data);
+
+		index = p->index_map.data;
+		level1_ofs = p->index_map.data;
+	}
+
+	if (p->index_version > 1) {
+		level1_ofs += 2;
+		index += 8;
+	}
+
+	index += 4 * 256;
+	hi = ntohl(level1_ofs[(int)oid->id[0]]);
+	lo = ((oid->id[0] == 0x0) ? 0 : ntohl(level1_ofs[(int)oid->id[0] - 1]));
+
+	if (p->index_version > 1) {
+		stride = 20;
+	} else {
+		stride = 24;
+		index += 4;
+	}
+
+#ifdef INDEX_DEBUG_LOOKUP
+	printf("%02x%02x%02x... lo %u hi %u nr %d\n",
+		oid->id[0], oid->id[1], oid->id[2], lo, hi, p->num_objects);
+#endif
+
+#ifdef GIT2_INDEX_LOOKUP /* TODO: use the advanced lookup method from git.git */
+
+	int pos = sha1_entry_pos(index, stride, 0, lo, hi, p->num_objects, oid);
+	if (pos < 0)
+		return GIT_ENOTFOUND;
+
+	*offset_out = nth_packed_object_offset(p, pos);
+	return GIT_SUCCESS;
+
+#else /* use an old and boring binary search */
+
+	do {
+		unsigned mi = (lo + hi) / 2;
+		int cmp = memcmp(index + mi * stride, oid->id, GIT_OID_RAWSZ);
+
+		if (!cmp) {
+			*offset_out = nth_packed_object_offset(p, mi);
+			return GIT_SUCCESS;
+		}
+
+		if (cmp > 0)
+			hi = mi;
+		else
+			lo = mi+1;
+
+	} while (lo < hi);
+
+	return GIT_ENOTFOUND;
+#endif
+}
+
+static int pack_entry_find1(
+		struct pack_entry *e,
+		struct pack_file *p,
+		const git_oid *oid)
+{
+	off_t offset;
+
+	assert(p);
+
+	if (p->num_bad_objects) {
+		unsigned i;
+		for (i = 0; i < p->num_bad_objects; i++)
+			if (git_oid_cmp(oid, &p->bad_object_sha1[i]) == 0)
+				return GIT_ERROR;
+	}
+
+	if (pack_entry_find_offset(&offset, p, oid) < GIT_SUCCESS)
+		return GIT_ENOTFOUND;
+	
+	/* we found an entry in the index;
+	 * make sure the packfile backing the index 
+	 * still exists on disk */
+	if (p->pack_fd == -1 && packfile_open(p) < GIT_SUCCESS)
+		return GIT_EOSERR;
+
+	e->offset = offset;
+	e->p = p;
+
+	git_oid_cpy(&e->sha1, oid);
+	return GIT_SUCCESS;
+}
+
+static int pack_entry_find(struct pack_entry *e, struct pack_backend *backend, const git_oid *oid)
+{
+	size_t i;
+
+	if (backend->last_found &&
+		pack_entry_find1(e, backend->last_found, oid) == GIT_SUCCESS)
+		return GIT_SUCCESS;
+
+	for (i = 0; i < backend->packs.length; ++i) {
+		struct pack_file *p;
+
+		p = git_vector_get(&backend->packs, i);
+		if (p == backend->last_found)
+			continue;
+
+		if (pack_entry_find1(e, p, oid) == GIT_SUCCESS) {
+			backend->last_found = p;
+			return GIT_SUCCESS;
+		}
+	}
+
+	return GIT_ENOTFOUND;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+/***********************************************************
+ *
+ * PACKFILE ENTRY UNPACK INTERNALS
+ *
+ ***********************************************************/
+
+static unsigned long packfile_unpack_header1(
+		size_t *sizep,
+		git_otype *type, 
+		const unsigned char *buf,
+		unsigned long len)
+{
+	unsigned shift;
+	unsigned long size, c;
+	unsigned long used = 0;
+
+	c = buf[used++];
+	*type = (c >> 4) & 7;
+	size = c & 15;
+	shift = 4;
+	while (c & 0x80) {
+		if (len <= used || bitsizeof(long) <= shift)
+			return 0;
+
+		c = buf[used++];
+		size += (c & 0x7f) << shift;
+		shift += 7;
+	}
+
+	*sizep = (size_t)size;
+	return used;
+}
+
+static int packfile_unpack_header(
+		size_t *size_p,
+		git_otype *type_p,
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_curs,
+		off_t *curpos)
+{
+	unsigned char *base;
+	unsigned int left;
+	unsigned long used;
+
+	/* pack_window_open() assures us we have [base, base + 20) available
+	 * as a range that we can look at at.  (Its actually the hash
+	 * size that is assured.)  With our object header encoding
+	 * the maximum deflated object size is 2^137, which is just
+	 * insane, so we know won't exceed what we have been given.
+	 */
+	base = pack_window_open(backend, p, w_curs, *curpos, &left);
+	if (base == NULL)
+		return GIT_ENOMEM;
+
+	used = packfile_unpack_header1(size_p, type_p, base, left);
+
+	if (used == 0)
+		return GIT_EOBJCORRUPTED;
+
+	*curpos += used;
+	return GIT_SUCCESS;
+}
+
+static int packfile_unpack_compressed(
+		git_rawobj *obj,
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_curs,
+		off_t curpos,
+		size_t size,
+		git_otype type)
+{
+	int st;
+	z_stream stream;
+	unsigned char *buffer, *in;
+
+	buffer = git__malloc(size);
+
+	memset(&stream, 0, sizeof(stream));
+	stream.next_out = buffer;
+	stream.avail_out = size + 1;
+
+	st = inflateInit(&stream);
+	if (st != Z_OK) {
+		free(buffer);
+		return GIT_EZLIB;
+	}
+
+	do {
+		in = pack_window_open(backend, p, w_curs, curpos, &stream.avail_in);
+		stream.next_in = in;
+		st = inflate(&stream, Z_FINISH);
+
+		if (!stream.avail_out)
+			break; /* the payload is larger than it should be */
+
+		curpos += stream.next_in - in;
+	} while (st == Z_OK || st == Z_BUF_ERROR);
+
+	inflateEnd(&stream);
+
+	if ((st != Z_STREAM_END) || stream.total_out != size) {
+		free(buffer);
+		return GIT_EZLIB;
+	}
+
+	obj->type = type;
+	obj->len = size;
+	obj->data = buffer;
+	return GIT_SUCCESS;
+}
+
+static off_t get_delta_base(
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_curs,
+		off_t *curpos,
+		git_otype type,
+		off_t delta_obj_offset)
+{
+	unsigned char *base_info = pack_window_open(backend, p, w_curs, *curpos, NULL);
+	off_t base_offset;
+
+	/* pack_window_open() assured us we have [base_info, base_info + 20)
+	 * as a range that we can look at without walking off the
+	 * end of the mapped window.  Its actually the hash size
+	 * that is assured.  An OFS_DELTA longer than the hash size
+	 * is stupid, as then a REF_DELTA would be smaller to store.
+	 */
+	if (type == GIT_OBJ_OFS_DELTA) {
+		unsigned used = 0;
+		unsigned char c = base_info[used++];
+		base_offset = c & 127;
+		while (c & 128) {
+			base_offset += 1;
+			if (!base_offset || MSB(base_offset, 7))
+				return 0;  /* overflow */
+			c = base_info[used++];
+			base_offset = (base_offset << 7) + (c & 127);
+		}
+		base_offset = delta_obj_offset - base_offset;
+		if (base_offset <= 0 || base_offset >= delta_obj_offset)
+			return 0;  /* out of bound */
+		*curpos += used;
+	} else if (type == GIT_OBJ_REF_DELTA) {
+		/* The base entry _must_ be in the same pack */
+		if (pack_entry_find_offset(&base_offset, p, (git_oid *)base_info) < GIT_SUCCESS)
+			return GIT_EPACKCORRUPTED;
+		*curpos += 20;
+	} else
+		return 0;
+
+	return base_offset;
+}
+
+static int packfile_unpack_delta(
+		git_rawobj *obj,
+		struct pack_backend *backend,
+		struct pack_file *p,
+		struct pack_window **w_curs,
+		off_t curpos,
+		size_t delta_size,
+		git_otype delta_type,
+		off_t obj_offset)
+{
+	off_t base_offset;
+	git_rawobj base, delta;
+	int error;
+
+	base_offset = get_delta_base(backend, p, w_curs, &curpos, delta_type, obj_offset);
+	if (base_offset == 0)
+		return GIT_EOBJCORRUPTED;
+
+	pack_window_close(w_curs);
+	error = packfile_unpack(&base, backend, p, base_offset);
+
+	/* TODO: git.git tries to load the base from other packfiles
+	 * or loose objects */
+	if (error < GIT_SUCCESS)
+		return error;
+
+	error = packfile_unpack_compressed(&delta, backend, p, w_curs, curpos, delta_size, delta_type);
+	if (error < GIT_SUCCESS) {
+		git_rawobj_close(&base);
+		return error;
+	}
+
+	obj->type = base.type;
+	error = git__delta_apply(obj,
+			base.data, base.len,
+			delta.data, delta.len);
+
+	git_rawobj_close(&base);
+	git_rawobj_close(&delta);
+
+	/* TODO: we might want to cache this shit. eventually */
+	//add_delta_base_cache(p, base_offset, base, base_size, *type);
+	return error;
+}
+
+static int packfile_unpack(
+		git_rawobj *obj,
+		struct pack_backend *backend,
+		struct pack_file *p,
+		off_t obj_offset)
+{
+	struct pack_window *w_curs = NULL;
+	off_t curpos = obj_offset;
+	int error;
+
+	size_t size;
+	git_otype type;
+
+	/* 
+	 * TODO: optionally check the CRC on the packfile
+	 */
+
+	obj->data = NULL;
+	obj->len = 0;
+	obj->type = GIT_OBJ_BAD;
+
+	error = packfile_unpack_header(&size, &type, backend, p, &w_curs, &curpos);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	switch (type) {
+	case GIT_OBJ_OFS_DELTA:
+	case GIT_OBJ_REF_DELTA:
+		error = packfile_unpack_delta(
+				obj, backend, p, &w_curs, curpos,
+				size, type, obj_offset);
+		break;
+
+	case GIT_OBJ_COMMIT:
+	case GIT_OBJ_TREE:
+	case GIT_OBJ_BLOB:
+	case GIT_OBJ_TAG:
+		error = packfile_unpack_compressed(
+				obj, backend, p, &w_curs, curpos,
+				size, type);
+		break;
+
+	default:
+		error = GIT_EOBJCORRUPTED;
+		break;
+	}
+
+	pack_window_close(&w_curs);
+	return error;
+}
+
+
+
+
+
+/***********************************************************
+ *
+ * PACKED BACKEND PUBLIC API
+ *
+ * Implement the git_odb_backend API calls
+ *
+ ***********************************************************/
+
+/*
+int pack_backend__read_header(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
+{
+	pack_location location;
+
+	assert(obj && backend && oid);
+
+	if (locate_packfile(&location, (struct pack_backend *)backend, oid) < 0)
+		return GIT_ENOTFOUND;
+
+	return read_header_packed(obj, &location);
+}
+*/
+
+int pack_backend__read(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
+{
+	struct pack_entry e;
+	int error;
+
+	if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < GIT_SUCCESS)
+		return error;
+
+	return packfile_unpack(obj, (struct pack_backend *)backend, e.p, e.offset);
+}
+
+int pack_backend__exists(git_odb_backend *backend, const git_oid *oid)
+{
+	struct pack_entry e;
+	return pack_entry_find(&e, (struct pack_backend *)backend, oid) == GIT_SUCCESS;
+}
+
+void pack_backend__free(git_odb_backend *_backend)
+{
+	struct pack_backend *backend;
+	size_t i;
+
+	assert(_backend);
+
+	backend = (struct pack_backend *)_backend;
+
+	for (i = 0; i < backend->packs.length; ++i) {
+		struct pack_file *p = git_vector_get(&backend->packs, i);
+		packfile_free(backend, p);
+	}
+
+	git_vector_free(&backend->packs);
+	free(backend);
+}
+
+int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
+{
+	int error;
+	struct pack_backend *backend;
+
+	backend = git__calloc(1, sizeof(struct pack_backend));
+	if (backend == NULL)
+		return GIT_ENOMEM;
+
+	if (git_vector_init(&backend->packs, 8, packfile_sort__cb) < GIT_SUCCESS) {
+		free(backend);
+		return GIT_ENOMEM;
+	}
+
+	backend->window_size = DEFAULT_WINDOW_SIZE;
+	backend->mapped_limit = DEFAULT_MAPPED_LIMIT;
+
+	error = packfile_load_all(backend, objects_dir, 1);
+	if (error < GIT_SUCCESS) {
+		pack_backend__free((git_odb_backend *)backend);
+		return error;
+	}
+
+	backend->parent.read = &pack_backend__read;
+	backend->parent.read_header = NULL;
+	backend->parent.write = NULL;
+	backend->parent.exists = &pack_backend__exists;
+	backend->parent.free = &pack_backend__free;
+
+	*backend_out = (git_odb_backend *)backend;
+	return GIT_SUCCESS;
+}
diff --git a/libgit2/src/oid.c b/libgit2/src/oid.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/oid.c
@@ -0,0 +1,346 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "git2/oid.h"
+#include "repository.h"
+#include <string.h>
+#include <limits.h>
+
+static signed char from_hex[] = {
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 */
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /* 30 */
+-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 */
+-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* b0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* c0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* d0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* e0 */
+-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* f0 */
+};
+static char to_hex[] = "0123456789abcdef";
+
+int git_oid_mkstr(git_oid *out, const char *str)
+{
+	size_t p;
+	for (p = 0; p < sizeof(out->id); p++, str += 2) {
+		int v = (from_hex[(unsigned char)str[0]] << 4)
+		       | from_hex[(unsigned char)str[1]];
+		if (v < 0)
+			return GIT_ENOTOID;
+		out->id[p] = (unsigned char)v;
+	}
+	return GIT_SUCCESS;
+}
+
+GIT_INLINE(char) *fmt_one(char *str, unsigned int val)
+{
+	*str++ = to_hex[val >> 4];
+	*str++ = to_hex[val & 0xf];
+	return str;
+}
+
+void git_oid_fmt(char *str, const git_oid *oid)
+{
+	size_t i;
+
+	for (i = 0; i < sizeof(oid->id); i++)
+		str = fmt_one(str, oid->id[i]);
+}
+
+void git_oid_pathfmt(char *str, const git_oid *oid)
+{
+	size_t i;
+
+	str = fmt_one(str, oid->id[0]);
+	*str++ = '/';
+	for (i = 1; i < sizeof(oid->id); i++)
+		str = fmt_one(str, oid->id[i]);
+}
+
+char *git_oid_allocfmt(const git_oid *oid)
+{
+	char *str = git__malloc(GIT_OID_HEXSZ + 1);
+	if (!str)
+		return NULL;
+	git_oid_fmt(str, oid);
+	str[GIT_OID_HEXSZ] = '\0';
+	return str;
+}
+
+char *git_oid_to_string(char *out, size_t n, const git_oid *oid)
+{
+	char str[GIT_OID_HEXSZ];
+
+	if (!out || n == 0 || !oid)
+		return "";
+
+	n--;  /* allow room for terminating NUL */
+
+	if (n > 0) {
+		git_oid_fmt(str, oid);
+		if (n > GIT_OID_HEXSZ)
+			n = GIT_OID_HEXSZ;
+		memcpy(out, str, n);
+	}
+
+	out[n] = '\0';
+
+	return out;
+}
+
+int git__parse_oid(git_oid *oid, char **buffer_out,
+		const char *buffer_end, const char *header)
+{
+	const size_t sha_len = GIT_OID_HEXSZ;
+	const size_t header_len = strlen(header);
+
+	char *buffer = *buffer_out;
+
+	if (buffer + (header_len + sha_len + 1) > buffer_end)
+		return GIT_EOBJCORRUPTED;
+
+	if (memcmp(buffer, header, header_len) != 0)
+		return GIT_EOBJCORRUPTED;
+
+	if (buffer[header_len + sha_len] != '\n')
+		return GIT_EOBJCORRUPTED;
+
+	if (git_oid_mkstr(oid, buffer + header_len) < GIT_SUCCESS)
+		return GIT_EOBJCORRUPTED;
+
+	*buffer_out = buffer + (header_len + sha_len + 1);
+
+	return GIT_SUCCESS;
+}
+
+int git__write_oid(git_odb_source *src, const char *header, const git_oid *oid)
+{
+	char hex_oid[41];
+
+	git_oid_fmt(hex_oid, oid);
+	hex_oid[40] = 0;
+
+	return git__source_printf(src, "%s %s\n", header, hex_oid);
+}
+
+void git_oid_mkraw(git_oid *out, const unsigned char *raw)
+{
+	memcpy(out->id, raw, sizeof(out->id));
+}
+
+void git_oid_cpy(git_oid *out, const git_oid *src)
+{
+	memcpy(out->id, src->id, sizeof(out->id));
+}
+
+int git_oid_cmp(const git_oid *a, const git_oid *b)
+{
+	return memcmp(a->id, b->id, sizeof(a->id));
+}
+
+
+typedef short node_index;
+
+typedef union {
+	const char *tail;
+	node_index children[16];
+} trie_node;
+
+struct git_oid_shorten {
+	trie_node *nodes;
+	size_t node_count, size;
+	int min_length, full;
+};
+
+static int resize_trie(git_oid_shorten *self, size_t new_size)
+{
+	self->nodes = realloc(self->nodes, new_size * sizeof(trie_node));
+	if (self->nodes == NULL)
+		return GIT_ENOMEM;
+
+	if (new_size > self->size) {
+		memset(&self->nodes[self->size], 0x0, (new_size - self->size) * sizeof(trie_node));
+	}
+
+	self->size = new_size;
+	return GIT_SUCCESS;
+}
+
+static trie_node *push_leaf(git_oid_shorten *os, node_index idx, int push_at, const char *oid)
+{
+	trie_node *node, *leaf;
+	node_index idx_leaf;
+
+	if (os->node_count >= os->size) {
+		if (resize_trie(os, os->size * 2) < GIT_SUCCESS)
+			return NULL;
+	}
+
+	idx_leaf = (node_index)os->node_count++;
+
+	if (os->node_count == SHRT_MAX)
+		os->full = 1;
+
+	node = &os->nodes[idx];
+	node->children[push_at] = -idx_leaf;
+
+	leaf = &os->nodes[idx_leaf];
+	leaf->tail = oid;
+
+	return node;
+}
+
+git_oid_shorten *git_oid_shorten_new(size_t min_length)
+{
+	git_oid_shorten *os;
+
+	os = git__malloc(sizeof(git_oid_shorten));
+	if (os == NULL)
+		return NULL;
+
+	memset(os, 0x0, sizeof(git_oid_shorten));
+
+	if (resize_trie(os, 16) < GIT_SUCCESS) {
+		free(os);
+		return NULL;
+	}
+
+	os->node_count = 1;
+	os->min_length = min_length;
+
+	return os;
+}
+
+void git_oid_shorten_free(git_oid_shorten *os)
+{
+	free(os->nodes);
+	free(os);
+}
+
+
+/*
+ * What wizardry is this?
+ *
+ * This is just a memory-optimized trie: basically a very fancy
+ * 16-ary tree, which is used to store the prefixes of the OID
+ * strings.
+ *
+ * Read more: http://en.wikipedia.org/wiki/Trie
+ *
+ * Magic that happens in this method:
+ *
+ *	- Each node in the trie is an union, so it can work both as
+ *	a normal node, or as a leaf.
+ *
+ *	- Each normal node points to 16 children (one for each possible
+ *	character in the oid). This is *not* stored in an array of
+ *	pointers, because in a 64-bit arch this would be sucking 
+ *	16*sizeof(void*) = 128 bytes of memory per node, which is fucking
+ *	insane. What we do is store Node Indexes, and use these indexes
+ *	to look up each node in the om->index array. These indexes are
+ *	signed shorts, so this limits the amount of unique OIDs that
+ *	fit in the structure to about 20000 (assuming a more or less uniform
+ *	distribution).
+ *
+ *	- All the nodes in om->index array are stored contiguously in
+ *	memory, and each of them is 32 bytes, so we fit 2x nodes per
+ *	cache line. Convenient for speed.
+ *
+ *	- To differentiate the leafs from the normal nodes, we store all
+ *	the indexes towards a leaf as a negative index (indexes to normal
+ *	nodes are positives). When we find that one of the children for
+ *	a node has a negative value, that means it's going to be a leaf.
+ *	This reduces the amount of indexes we have by two, but also reduces
+ *	the size of each node by 1-4 bytes (the amount we would need to
+ *	add a `is_leaf` field): this is good because it allows the nodes
+ *	to fit cleanly in cache lines.
+ *
+ *	- Once we reach an empty children, instead of continuing to insert
+ *	new nodes for each remaining character of the OID, we store a pointer
+ *	to the tail in the leaf; if the leaf is reached again, we turn it
+ *	into a normal node and use the tail to create a new leaf.
+ *
+ *	This is a pretty good balance between performance and memory usage.
+ */
+int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid)
+{
+	int i, is_leaf;
+	node_index idx;
+
+	if (os->full)
+		return GIT_ENOMEM;
+
+	idx = 0;
+	is_leaf = 0;
+
+	for (i = 0; i < GIT_OID_HEXSZ; ++i) {
+		int c = from_hex[(int)text_oid[i]];
+		trie_node *node;
+
+		if (c == -1)
+			return GIT_ENOTOID;
+
+		node = &os->nodes[idx];
+
+		if (is_leaf) {
+			const char *tail;
+
+			tail = node->tail;
+			node->tail = NULL;
+
+			node = push_leaf(os, idx, from_hex[(int)tail[0]], &tail[1]);
+			if (node == NULL)
+				return GIT_ENOMEM;
+		}
+
+		if (node->children[c] == 0) {
+			if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL)
+				return GIT_ENOMEM;
+			break;
+		}
+
+		idx = node->children[c];
+		is_leaf = 0;
+
+		if (idx < 0) {
+			node->children[c] = idx = -idx;
+			is_leaf = 1;
+		}
+	}
+
+	if (++i > os->min_length)
+		os->min_length = i;
+
+	return os->min_length;
+}
+
diff --git a/libgit2/src/pqueue.c b/libgit2/src/pqueue.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/pqueue.c
@@ -0,0 +1,157 @@
+/*
+ *	BORING COPYRIGHT NOTICE:
+ *
+ *	This file is a heavily modified version of the priority queue found
+ *	in the Apache project and the libpqueue library.
+ *
+ *		https://github.com/vy/libpqueue
+ *
+ *	These are the original authors:
+ *
+ *		Copyright 2010 Volkan Yazıcı <volkan.yazici@gmail.com>
+ *		Copyright 2006-2010 The Apache Software Foundation
+ *
+ *  This file is licensed under the Apache 2.0 license, which 
+ *  supposedly makes it compatible with the GPLv2 that libgit2 uses.
+ *
+ *  Check the Apache license at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  So much licensing trouble for a binary heap. Oh well.
+ */
+
+#include "common.h"
+#include "pqueue.h"
+
+#define left(i)   ((i) << 1)
+#define right(i)  (((i) << 1) + 1)
+#define parent(i) ((i) >> 1)
+
+int git_pqueue_init(git_pqueue *q, size_t n, git_pqueue_cmp cmppri)
+{
+	assert(q);
+
+    /* Need to allocate n+1 elements since element 0 isn't used. */
+    if ((q->d = malloc((n + 1) * sizeof(void *))) == NULL)
+		return GIT_ENOMEM;
+
+    q->size = 1;
+    q->avail = q->step = (n + 1);  /* see comment above about n+1 */
+    q->cmppri = cmppri;
+
+    return GIT_SUCCESS;
+}
+
+
+void git_pqueue_free(git_pqueue *q)
+{
+    free(q->d);
+	q->d = NULL;
+}
+
+void git_pqueue_clear(git_pqueue *q)
+{
+	q->size = 1;
+}
+
+size_t git_pqueue_size(git_pqueue *q)
+{
+    /* queue element 0 exists but doesn't count since it isn't used. */
+    return (q->size - 1);
+}
+
+
+static void bubble_up(git_pqueue *q, size_t i)
+{
+    size_t parent_node;
+    void *moving_node = q->d[i];
+
+    for (parent_node = parent(i);
+         ((i > 1) && q->cmppri(q->d[parent_node], moving_node));
+         i = parent_node, parent_node = parent(i)) {
+        q->d[i] = q->d[parent_node];
+    }
+
+    q->d[i] = moving_node;
+}
+
+
+static size_t maxchild(git_pqueue *q, size_t i)
+{
+    size_t child_node = left(i);
+
+    if (child_node >= q->size)
+        return 0;
+
+    if ((child_node + 1) < q->size &&
+        q->cmppri(q->d[child_node], q->d[child_node + 1]))
+        child_node++; /* use right child instead of left */
+
+    return child_node;
+}
+
+
+static void percolate_down(git_pqueue *q, size_t i)
+{
+    size_t child_node;
+    void *moving_node = q->d[i];
+
+    while ((child_node = maxchild(q, i)) != 0 &&
+           q->cmppri(moving_node, q->d[child_node])) {
+        q->d[i] = q->d[child_node];
+        i = child_node;
+    }
+
+    q->d[i] = moving_node;
+}
+
+
+int git_pqueue_insert(git_pqueue *q, void *d)
+{
+    void *tmp;
+    size_t i;
+    size_t newsize;
+
+    if (!q) return 1;
+
+    /* allocate more memory if necessary */
+    if (q->size >= q->avail) {
+        newsize = q->size + q->step;
+        if ((tmp = realloc(q->d, sizeof(void *) * newsize)) == NULL)
+            return GIT_ENOMEM;
+
+        q->d = tmp;
+        q->avail = newsize;
+    }
+
+    /* insert item */
+    i = q->size++;
+    q->d[i] = d;
+    bubble_up(q, i);
+
+    return GIT_SUCCESS;
+}
+
+
+void *git_pqueue_pop(git_pqueue *q)
+{
+    void *head;
+
+    if (!q || q->size == 1)
+        return NULL;
+
+    head = q->d[1];
+    q->d[1] = q->d[--q->size];
+    percolate_down(q, 1);
+
+    return head;
+}
+
+
+void *git_pqueue_peek(git_pqueue *q)
+{
+    if (!q || q->size == 1)
+        return NULL;
+    return q->d[1];
+}
diff --git a/libgit2/src/pqueue.h b/libgit2/src/pqueue.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/pqueue.h
@@ -0,0 +1,97 @@
+/*
+ *	BORING COPYRIGHT NOTICE:
+ *
+ *	This file is a heavily modified version of the priority queue found
+ *	in the Apache project and the libpqueue library.
+ *
+ *		https://github.com/vy/libpqueue
+ *
+ *	These are the original authors:
+ *
+ *		Copyright 2010 Volkan Yazıcı <volkan.yazici@gmail.com>
+ *		Copyright 2006-2010 The Apache Software Foundation
+ *
+ *  This file is licensed under the Apache 2.0 license, which 
+ *  supposedly makes it compatible with the GPLv2 that libgit2 uses.
+ *
+ *  Check the Apache license at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  So much licensing trouble for a binary heap. Oh well.
+ */
+
+#ifndef INCLUDE_pqueue_h__
+#define INCLUDE_pqueue_h__
+
+/** callback functions to get/set/compare the priority of an element */
+typedef int (*git_pqueue_cmp)(void *a, void *b);
+
+/** the priority queue handle */
+typedef struct {
+    size_t size, avail, step;
+    git_pqueue_cmp cmppri;
+    void **d;
+} git_pqueue;
+
+
+/**
+ * initialize the queue
+ *
+ * @param n the initial estimate of the number of queue items for which memory
+ *          should be preallocated
+ * @param cmppri the callback function to compare two nodes of the queue
+ *
+ * @Return the handle or NULL for insufficent memory
+ */
+int git_pqueue_init(git_pqueue *q, size_t n, git_pqueue_cmp cmppri);
+
+
+/**
+ * free all memory used by the queue
+ * @param q the queue
+ */
+void git_pqueue_free(git_pqueue *q);
+
+/**
+ * clear all the elements in the queue
+ * @param q the queue
+ */
+void git_pqueue_clear(git_pqueue *q);
+
+/**
+ * return the size of the queue.
+ * @param q the queue
+ */
+size_t git_pqueue_size(git_pqueue *q);
+
+
+/**
+ * insert an item into the queue.
+ * @param q the queue
+ * @param d the item
+ * @return 0 on success
+ */
+int git_pqueue_insert(git_pqueue *q, void *d);
+
+
+/**
+ * pop the highest-ranking item from the queue.
+ * @param p the queue
+ * @param d where to copy the entry to
+ * @return NULL on error, otherwise the entry
+ */
+void *git_pqueue_pop(git_pqueue *q);
+
+
+/**
+ * access highest-ranking item without removing it.
+ * @param q the queue
+ * @param d the entry
+ * @return NULL on error, otherwise the entry
+ */
+void *git_pqueue_peek(git_pqueue *q);
+
+#endif /* PQUEUE_H */
+/** @} */
+
diff --git a/libgit2/src/refs.c b/libgit2/src/refs.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/refs.c
@@ -0,0 +1,1594 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "refs.h"
+#include "hash.h"
+#include "repository.h"
+#include "fileops.h"
+
+#include <git2/tag.h>
+#include <git2/object.h>
+
+#define MAX_NESTING_LEVEL 5
+
+typedef struct {
+	git_reference ref;
+	git_oid oid;
+	git_oid peel_target;
+} reference_oid;
+
+typedef struct {
+	git_reference ref;
+	char *target;
+} reference_symbolic;
+
+static const int default_table_size = 32;
+
+static uint32_t reftable_hash(const void *key, int hash_id)
+{
+	static uint32_t hash_seeds[GIT_HASHTABLE_HASHES] = {
+		2147483647,
+		0x5d20bb23,
+		0x7daaab3c 
+	};
+
+	return git__hash(key, strlen((const char *)key), hash_seeds[hash_id]);
+}
+
+static void reference_free(git_reference *reference);
+static int reference_create(git_reference **ref_out, git_repository *repo, const char *name, git_rtype type);
+static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *repo_path, const char *ref_name);
+
+/* loose refs */
+static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content);
+static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content);
+static int loose_lookup(git_reference **ref_out, git_repository *repo, const char *name, int skip_symbolic);
+static int loose_write(git_reference *ref);
+static int loose_update(git_reference *ref);
+
+/* packed refs */
+static int packed_parse_peel(reference_oid *tag_ref, const char **buffer_out, const char *buffer_end);
+static int packed_parse_oid(reference_oid **ref_out, git_repository *repo, const char **buffer_out, const char *buffer_end);
+static int packed_load(git_repository *repo);
+static int packed_loadloose(git_repository *repository);
+static int packed_write_ref(reference_oid *ref, git_filebuf *file);
+static int packed_find_peel(reference_oid *ref);
+static int packed_remove_loose(git_repository *repo, git_vector *packing_list);
+static int packed_sort(const void *a, const void *b);
+static int packed_write(git_repository *repo);
+
+/* name normalization */
+static int check_valid_ref_char(char ch);
+static int normalize_name(char *buffer_out, const char *name, int is_oid_ref);
+
+/*****************************************
+ * Internal methods - Constructor/destructor
+ *****************************************/
+static void reference_free(git_reference *reference)
+{
+	if (reference == NULL)
+		return;
+
+	if (reference->name)
+		free(reference->name);
+
+	if (reference->type == GIT_REF_SYMBOLIC)
+		free(((reference_symbolic *)reference)->target);
+
+	free(reference);
+}
+
+static int reference_create(
+	git_reference **ref_out,
+	git_repository *repo,
+	const char *name,
+	git_rtype type)
+{
+	char normalized[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
+	int error = GIT_SUCCESS, size;
+	git_reference *reference = NULL;
+
+	assert(ref_out && repo && name);
+
+	if (type == GIT_REF_SYMBOLIC)
+		size = sizeof(reference_symbolic);
+	else if (type == GIT_REF_OID)
+		size = sizeof(reference_oid);
+	else
+		return GIT_EINVALIDREFSTATE;
+
+	reference = git__malloc(size);
+	if (reference == NULL)
+		return GIT_ENOMEM;
+
+	memset(reference, 0x0, size);
+	reference->owner = repo;
+	reference->type = type;
+
+	error = normalize_name(normalized, name, (type & GIT_REF_OID));
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	reference->name = git__strdup(normalized);
+	if (reference->name == NULL) {
+		error = GIT_ENOMEM;
+		goto cleanup;
+	}
+
+	*ref_out = reference;
+
+	return error;
+
+cleanup:
+	reference_free(reference);
+	return error;
+}
+
+static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *repo_path, const char *ref_name)
+{
+	struct stat st;
+	char path[GIT_PATH_MAX];
+
+	/* Determine the full path of the file */
+	git__joinpath(path, repo_path, ref_name);
+
+	if (gitfo_stat(path, &st) < 0)
+		return GIT_ENOTFOUND;
+
+	if (S_ISDIR(st.st_mode))
+		return GIT_EOBJCORRUPTED;
+
+	if (mtime)
+		*mtime = st.st_mtime;
+
+	if (file_content)
+		return gitfo_read_file(file_content, path);
+
+	return GIT_SUCCESS;
+}
+
+
+
+
+/*****************************************
+ * Internal methods - Loose references
+ *****************************************/
+static int loose_update(git_reference *ref)
+{
+	int error;
+	time_t ref_time;
+	gitfo_buf ref_file = GITFO_BUF_INIT;
+
+	if (ref->type & GIT_REF_PACKED)
+		return packed_load(ref->owner);
+
+	error = reference_read(NULL, &ref_time, ref->owner->path_repository, ref->name);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	if (ref_time == ref->mtime)
+		return GIT_SUCCESS;
+
+	error = reference_read(&ref_file, &ref->mtime, ref->owner->path_repository, ref->name);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	if (ref->type == GIT_REF_SYMBOLIC)
+		error = loose_parse_symbolic(ref, &ref_file);
+	else if (ref->type == GIT_REF_OID)
+		error = loose_parse_oid(ref, &ref_file);
+	else
+		error = GIT_EINVALIDREFSTATE;
+
+	gitfo_free_buf(&ref_file);
+
+cleanup:
+	if (error != GIT_SUCCESS) {
+		reference_free(ref);
+		git_hashtable_remove(ref->owner->references.loose_cache, ref->name);
+	}
+
+	return error;
+}
+
+static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
+{
+	const unsigned int header_len = strlen(GIT_SYMREF);
+	const char *refname_start;
+	char *eol;
+	reference_symbolic *ref_sym;
+
+	refname_start = (const char *)file_content->data;
+	ref_sym = (reference_symbolic *)ref;
+
+	if (file_content->len < (header_len + 1))
+		return GIT_EREFCORRUPTED;
+
+	/* 
+	 * Assume we have already checked for the header
+	 * before calling this function 
+	 */
+
+	refname_start += header_len;
+
+	free(ref_sym->target);
+	ref_sym->target = git__strdup(refname_start);
+	if (ref_sym->target == NULL)
+		return GIT_ENOMEM;
+
+	/* remove newline at the end of file */
+	eol = strchr(ref_sym->target, '\n');
+	if (eol == NULL)
+		return GIT_EREFCORRUPTED;
+
+	*eol = '\0';
+	if (eol[-1] == '\r')
+		eol[-1] = '\0';
+
+	return GIT_SUCCESS;
+}
+
+static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
+{
+	reference_oid *ref_oid;
+	char *buffer;
+
+	buffer = (char *)file_content->data;
+	ref_oid = (reference_oid *)ref;
+
+	/* File format: 40 chars (OID) + newline */
+	if (file_content->len < GIT_OID_HEXSZ + 1)
+		return GIT_EREFCORRUPTED;
+
+	if (git_oid_mkstr(&ref_oid->oid, buffer) < GIT_SUCCESS)
+		return GIT_EREFCORRUPTED;
+
+	buffer = buffer + GIT_OID_HEXSZ;
+	if (*buffer == '\r')
+		buffer++;
+
+	if (*buffer != '\n')
+		return GIT_EREFCORRUPTED;
+
+	return GIT_SUCCESS;
+}
+
+
+static git_rtype loose_guess_rtype(const char *full_path)
+{
+	gitfo_buf ref_file = GITFO_BUF_INIT;
+	git_rtype type;
+
+	type = GIT_REF_INVALID;
+
+	if (gitfo_read_file(&ref_file, full_path) == GIT_SUCCESS) {
+		if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0)
+			type = GIT_REF_SYMBOLIC;
+		else
+			type = GIT_REF_OID;
+	}
+
+	gitfo_free_buf(&ref_file);
+	return type;
+}
+
+static int loose_lookup(
+		git_reference **ref_out, 
+		git_repository *repo, 
+		const char *name,
+		int skip_symbolic)
+{
+	int error = GIT_SUCCESS;
+	gitfo_buf ref_file = GITFO_BUF_INIT;
+	git_reference *ref = NULL;
+	time_t ref_time;
+
+	*ref_out = NULL;
+
+	error = reference_read(&ref_file, &ref_time, repo->path_repository, name);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0) {
+		if (skip_symbolic)
+			return GIT_SUCCESS;
+
+		error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+
+		error = loose_parse_symbolic(ref, &ref_file);
+	} else {
+		error = reference_create(&ref, repo, name, GIT_REF_OID);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+
+		error = loose_parse_oid(ref, &ref_file);
+	}
+
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	ref->mtime = ref_time;
+	*ref_out = ref;
+	return GIT_SUCCESS;
+
+cleanup:
+	gitfo_free_buf(&ref_file);
+	reference_free(ref);
+	return error;
+}
+
+static int loose_write(git_reference *ref)
+{
+	git_filebuf file;
+	char ref_path[GIT_PATH_MAX];
+	int error, contents_size;
+	char *ref_contents = NULL;
+	struct stat st;
+
+	assert((ref->type & GIT_REF_PACKED) == 0);
+
+	git__joinpath(ref_path, ref->owner->path_repository, ref->name);
+
+	if ((error = git_filebuf_open(&file, ref_path, GIT_FILEBUF_FORCE)) < GIT_SUCCESS)
+		return error;
+
+	if (ref->type & GIT_REF_OID) {
+		reference_oid *ref_oid = (reference_oid *)ref;
+
+		contents_size = GIT_OID_HEXSZ + 1;
+		ref_contents = git__malloc(contents_size);
+		if (ref_contents == NULL) {
+			error = GIT_ENOMEM;
+			goto unlock;
+		}
+
+		git_oid_fmt(ref_contents, &ref_oid->oid);
+
+	} else if (ref->type & GIT_REF_SYMBOLIC) { /* GIT_REF_SYMBOLIC */
+		reference_symbolic *ref_sym = (reference_symbolic *)ref;
+
+		contents_size = strlen(GIT_SYMREF) + strlen(ref_sym->target) + 1;
+		ref_contents = git__malloc(contents_size);
+		if (ref_contents == NULL) {
+			error = GIT_ENOMEM;
+			goto unlock;
+		}
+
+		strcpy(ref_contents, GIT_SYMREF);
+		strcat(ref_contents, ref_sym->target);
+	} else {
+		error = GIT_EINVALIDREFSTATE;
+		goto unlock;
+	}
+
+	/* TODO: win32 carriage return when writing references in Windows? */
+	ref_contents[contents_size - 1] = '\n';
+
+	if ((error = git_filebuf_write(&file, ref_contents, contents_size)) < GIT_SUCCESS)
+		goto unlock;
+
+	error = git_filebuf_commit(&file);
+
+	if (gitfo_stat(ref_path, &st) == GIT_SUCCESS)
+		ref->mtime = st.st_mtime;
+
+	free(ref_contents);
+	return error;
+
+unlock:
+	git_filebuf_cleanup(&file);
+	free(ref_contents);
+	return error;
+}
+
+
+
+
+
+
+/*****************************************
+ * Internal methods - Packed references
+ *****************************************/
+
+static int packed_parse_peel(
+		reference_oid *tag_ref,
+		const char **buffer_out, 
+		const char *buffer_end)
+{
+	const char *buffer = *buffer_out + 1;
+
+	assert(buffer[-1] == '^');
+
+	/* Ensure it's not the first entry of the file */
+	if (tag_ref == NULL)
+		return GIT_EPACKEDREFSCORRUPTED;
+
+	/* Ensure reference is a tag */
+	if (git__prefixcmp(tag_ref->ref.name, GIT_REFS_TAGS_DIR) != 0)
+		return GIT_EPACKEDREFSCORRUPTED;
+
+	if (buffer + GIT_OID_HEXSZ >= buffer_end)
+		return GIT_EPACKEDREFSCORRUPTED;
+
+	/* Is this a valid object id? */
+	if (git_oid_mkstr(&tag_ref->peel_target, buffer) < GIT_SUCCESS)
+		return GIT_EPACKEDREFSCORRUPTED;
+
+	buffer = buffer + GIT_OID_HEXSZ;
+	if (*buffer == '\r')
+		buffer++;
+
+	if (*buffer != '\n')
+		return GIT_EPACKEDREFSCORRUPTED;
+
+	*buffer_out = buffer + 1;
+	tag_ref->ref.type |= GIT_REF_HAS_PEEL;
+
+	return GIT_SUCCESS;
+}
+
+static int packed_parse_oid(
+		reference_oid **ref_out,
+		git_repository *repo,
+		const char **buffer_out,
+		const char *buffer_end)
+{
+	reference_oid *ref = NULL;
+
+	const char *buffer = *buffer_out;
+	const char *refname_begin, *refname_end;
+
+	int error = GIT_SUCCESS;
+	int refname_len;
+	char refname[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
+	git_oid id;
+
+	refname_begin = (buffer + GIT_OID_HEXSZ + 1);
+	if (refname_begin >= buffer_end ||
+		refname_begin[-1] != ' ') {
+		error = GIT_EPACKEDREFSCORRUPTED;
+		goto cleanup;
+	}
+
+	/* Is this a valid object id? */
+	if ((error = git_oid_mkstr(&id, buffer)) < GIT_SUCCESS)
+		goto cleanup;
+
+	refname_end = memchr(refname_begin, '\n', buffer_end - refname_begin);
+	if (refname_end == NULL) {
+		error = GIT_EPACKEDREFSCORRUPTED;
+		goto cleanup;
+	}
+
+	refname_len = refname_end - refname_begin;
+
+	memcpy(refname, refname_begin, refname_len);
+	refname[refname_len] = 0;
+
+	if (refname[refname_len - 1] == '\r')
+		refname[refname_len - 1] = 0;
+
+	error = reference_create((git_reference **)&ref, repo, refname, GIT_REF_OID);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	git_oid_cpy(&ref->oid, &id);
+	ref->ref.type |= GIT_REF_PACKED;
+
+	*ref_out = ref;
+	*buffer_out = refname_end + 1;
+
+	return GIT_SUCCESS;
+
+cleanup:
+	reference_free((git_reference *)ref);
+	return error;
+}
+
+static int packed_load(git_repository *repo)
+{
+	int error = GIT_SUCCESS;
+	gitfo_buf packfile = GITFO_BUF_INIT;
+	const char *buffer_start, *buffer_end;
+	git_refcache *ref_cache = &repo->references;
+
+	/* already loaded */
+	if (repo->references.packfile != NULL) {
+		time_t packed_time;
+
+		/* check if we can read the time of the index;
+		 * if we can read it and it matches the time of the
+		 * index we had previously loaded, we don't need to do
+		 * anything else.
+		 *
+		 * if we cannot load the time (e.g. the packfile
+		 * has disappeared) or the time is different, we
+		 * have to reload the packfile */
+
+		if (!reference_read(NULL, &packed_time, repo->path_repository, GIT_PACKEDREFS_FILE) &&
+			packed_time == ref_cache->packfile_time)
+			return GIT_SUCCESS;
+
+		git_hashtable_clear(repo->references.packfile);
+	} else {
+		ref_cache->packfile = git_hashtable_alloc(
+			default_table_size, 
+			reftable_hash,
+			(git_hash_keyeq_ptr)strcmp);
+
+		if (ref_cache->packfile == NULL)
+			return GIT_ENOMEM;
+	}
+
+	/* read the packfile from disk;
+	 * store its modification time to check for future reloads */
+	error = reference_read(
+			&packfile,
+			&ref_cache->packfile_time,
+			repo->path_repository,
+			GIT_PACKEDREFS_FILE);
+
+	/* there is no packfile on disk; that's ok */
+	if (error == GIT_ENOTFOUND)
+		return GIT_SUCCESS;
+
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	buffer_start = (const char *)packfile.data;
+	buffer_end = (const char *)(buffer_start) + packfile.len;
+
+	while (buffer_start < buffer_end && buffer_start[0] == '#') {
+		buffer_start = strchr(buffer_start, '\n');
+		if (buffer_start == NULL) {
+			error = GIT_EPACKEDREFSCORRUPTED;
+			goto cleanup;
+		}
+		buffer_start++;
+	}
+
+	while (buffer_start < buffer_end) {
+		reference_oid *ref = NULL;
+
+		error = packed_parse_oid(&ref, repo, &buffer_start, buffer_end);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+
+		if (buffer_start[0] == '^') {
+			error = packed_parse_peel(ref, &buffer_start, buffer_end);
+			if (error < GIT_SUCCESS)
+				goto cleanup;
+		}
+
+		error = git_hashtable_insert(ref_cache->packfile, ref->ref.name, ref);
+		if (error < GIT_SUCCESS) {
+			reference_free((git_reference *)ref);
+			goto cleanup;
+		}
+	}
+
+	gitfo_free_buf(&packfile);
+	return GIT_SUCCESS;
+
+cleanup:
+	git_hashtable_free(ref_cache->packfile);
+	ref_cache->packfile = NULL;
+	gitfo_free_buf(&packfile);
+	return error;
+}
+
+
+
+
+struct dirent_list_data {
+	git_vector ref_list;
+	git_repository *repo;
+	size_t repo_path_len;
+	unsigned int list_flags;
+};
+
+static int _dirent_loose_listall(void *_data, char *full_path)
+{
+	struct dirent_list_data *data = (struct dirent_list_data *)_data;
+	char *file_path = full_path + data->repo_path_len;
+
+	if (gitfo_isdir(full_path) == GIT_SUCCESS)
+		return gitfo_dirent(full_path, GIT_PATH_MAX, _dirent_loose_listall, _data);
+
+	/* do not add twice a reference that exists already in the packfile */
+	if ((data->list_flags & GIT_REF_PACKED) != 0 &&
+		git_hashtable_lookup(data->repo->references.packfile, file_path) != NULL)
+		return GIT_SUCCESS;
+
+	if ((data->list_flags & loose_guess_rtype(full_path)) == 0)
+		return GIT_SUCCESS; /* we are filtering out this reference */
+
+	return git_vector_insert(&data->ref_list, git__strdup(file_path));
+}
+
+static int _dirent_loose_load(void *data, char *full_path)
+{
+	git_repository *repository = (git_repository *)data;
+	git_reference *reference, *old_ref;
+	char *file_path;
+	int error;
+
+	if (gitfo_isdir(full_path) == GIT_SUCCESS)
+		return gitfo_dirent(full_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+
+	file_path = full_path + strlen(repository->path_repository);
+	error = loose_lookup(&reference, repository, file_path, 1);
+	if (error == GIT_SUCCESS && reference != NULL) {
+		reference->type |= GIT_REF_PACKED;
+
+		if (git_hashtable_insert2(repository->references.packfile, reference->name, reference, (void **)&old_ref) < GIT_SUCCESS) {
+			reference_free(reference);
+			return GIT_ENOMEM;
+		}
+
+		if (old_ref != NULL)
+			reference_free(old_ref);
+	}
+
+	return error;
+}
+
+/*
+ * Load all the loose references from the repository
+ * into the in-memory Packfile, and build a vector with
+ * all the references so it can be written back to
+ * disk.
+ */
+static int packed_loadloose(git_repository *repository)
+{
+	char refs_path[GIT_PATH_MAX];
+
+	/* the packfile must have been previously loaded! */
+	assert(repository->references.packfile);
+
+	git__joinpath(refs_path, repository->path_repository, GIT_REFS_DIR);
+
+	/* Remove any loose references from the cache */
+	{
+		const void *_unused;
+		git_reference *reference;
+
+		GIT_HASHTABLE_FOREACH(repository->references.loose_cache, _unused, reference,
+			reference_free(reference);
+		);
+	}
+
+	git_hashtable_clear(repository->references.loose_cache);
+
+	/*
+	 * Load all the loose files from disk into the Packfile table.
+	 * This will overwrite any old packed entries with their
+	 * updated loose versions 
+	 */
+	return gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+}
+
+/*
+ * Write a single reference into a packfile
+ */
+static int packed_write_ref(reference_oid *ref, git_filebuf *file)
+{
+	int error;
+	char oid[GIT_OID_HEXSZ + 1];
+
+	git_oid_fmt(oid, &ref->oid);
+	oid[GIT_OID_HEXSZ] = 0;
+
+	/* 
+	 * For references that peel to an object in the repo, we must
+	 * write the resulting peel on a separate line, e.g.
+	 *
+	 *	6fa8a902cc1d18527e1355773c86721945475d37 refs/tags/libgit2-0.4
+	 *	^2ec0cb7959b0bf965d54f95453f5b4b34e8d3100
+	 *
+	 * This obviously only applies to tags.
+	 * The required peels have already been loaded into `ref->peel_target`.
+	 */
+	if (ref->ref.type & GIT_REF_HAS_PEEL) {
+		char peel[GIT_OID_HEXSZ + 1];
+		git_oid_fmt(peel, &ref->peel_target);
+		peel[GIT_OID_HEXSZ] = 0;
+
+		error = git_filebuf_printf(file, "%s %s\n^%s\n", oid, ref->ref.name, peel);
+	} else {
+		error = git_filebuf_printf(file, "%s %s\n", oid, ref->ref.name);
+	}
+
+	return error;
+}
+
+/*
+ * Find out what object this reference resolves to.
+ *
+ * For references that point to a 'big' tag (e.g. an 
+ * actual tag object on the repository), we need to
+ * cache on the packfile the OID of the object to
+ * which that 'big tag' is pointing to.
+ */
+static int packed_find_peel(reference_oid *ref)
+{
+	git_tag *tag;
+	int error;
+
+	if (ref->ref.type & GIT_REF_HAS_PEEL)
+		return GIT_SUCCESS;
+
+	/*
+	 * Only applies to tags, i.e. references
+	 * in the /refs/tags folder
+	 */
+	if (git__prefixcmp(ref->ref.name, GIT_REFS_TAGS_DIR) != 0)
+		return GIT_SUCCESS;
+
+	/*
+	 * Find the tag in the repository. The tag must exist,
+	 * otherwise this reference is broken and we shouldn't
+	 * pack it.
+	 */
+	error = git_tag_lookup(&tag, ref->ref.owner, &ref->oid);
+	if (error < GIT_SUCCESS)
+		return GIT_EOBJCORRUPTED;
+
+	/*
+	 * Find the object pointed at by this tag
+	 */
+	git_oid_cpy(&ref->peel_target, git_tag_target_oid(tag));
+	ref->ref.type |= GIT_REF_HAS_PEEL;
+
+	/* 
+	 * The reference has now cached the resolved OID, and is
+	 * marked at such. When written to the packfile, it'll be
+	 * accompanied by this resolved oid
+	 */
+
+	return GIT_SUCCESS;
+}
+
+/*
+ * Remove all loose references
+ *
+ * Once we have successfully written a packfile,
+ * all the loose references that were packed must be
+ * removed from disk.
+ *
+ * This is a dangerous method; make sure the packfile
+ * is well-written, because we are destructing references
+ * here otherwise.
+ */
+static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
+{
+	unsigned int i;
+	char full_path[GIT_PATH_MAX];
+	int error = GIT_SUCCESS;
+	git_reference *reference;
+
+	for (i = 0; i < packing_list->length; ++i) {
+		git_reference *ref = git_vector_get(packing_list, i);
+
+		/* Ensure the packed reference doesn't exist
+		 * in a (more up-to-date?) state as a loose reference
+		 */
+		reference = git_hashtable_lookup(ref->owner->references.loose_cache, ref->name);
+		if (reference != NULL)
+			continue;
+
+		git__joinpath(full_path, repo->path_repository, ref->name);
+
+		if (gitfo_exists(full_path) == GIT_SUCCESS &&
+			gitfo_unlink(full_path) < GIT_SUCCESS)
+			error = GIT_EOSERR;
+
+		/*
+		 * if we fail to remove a single file, this is *not* good,
+		 * but we should keep going and remove as many as possible.
+		 * After we've removed as many files as possible, we return
+		 * the error code anyway.
+		 *
+		 * TODO: mark this with a very special error code?
+		 * GIT_EFAILTORMLOOSE
+		 */
+	}
+
+	return error;
+}
+
+static int packed_sort(const void *a, const void *b)
+{
+	const git_reference *ref_a = *(const git_reference **)a;
+	const git_reference *ref_b = *(const git_reference **)b;
+
+	return strcmp(ref_a->name, ref_b->name);
+}
+
+/*
+ * Write all the contents in the in-memory packfile to disk.
+ */
+static int packed_write(git_repository *repo)
+{
+	git_filebuf pack_file;
+	int error;
+	unsigned int i;
+	char pack_file_path[GIT_PATH_MAX];
+
+	git_vector packing_list;
+	size_t total_refs;
+
+	assert(repo && repo->references.packfile);
+
+	total_refs = repo->references.packfile->key_count;
+	if ((error = git_vector_init(&packing_list, total_refs, packed_sort)) < GIT_SUCCESS)
+		return error;
+
+	/* Load all the packfile into a vector */
+	{
+		git_reference *reference;
+		const void *_unused;
+
+		GIT_HASHTABLE_FOREACH(repo->references.packfile, _unused, reference,
+			git_vector_insert(&packing_list, reference);  /* cannot fail: vector already has the right size */
+		);
+	}
+
+	/* sort the vector so the entries appear sorted on the packfile */
+	git_vector_sort(&packing_list);
+
+	/* Now we can open the file! */
+	git__joinpath(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
+	if ((error = git_filebuf_open(&pack_file, pack_file_path, 0)) < GIT_SUCCESS)
+		return error;
+
+	/* Packfiles have a header... apparently
+	 * This is in fact not required, but we might as well print it
+	 * just for kicks */
+	if ((error = git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER)) < GIT_SUCCESS)
+		return error;
+
+	for (i = 0; i < packing_list.length; ++i) {
+		reference_oid *ref = (reference_oid *)git_vector_get(&packing_list, i);
+
+		/* only direct references go to the packfile; otherwise
+		 * this is a disaster */
+		assert(ref->ref.type & GIT_REF_OID);
+
+		if ((error = packed_find_peel(ref)) < GIT_SUCCESS)
+			goto cleanup;
+
+		if ((error = packed_write_ref(ref, &pack_file)) < GIT_SUCCESS)
+			goto cleanup;
+	}
+
+cleanup:
+	/* if we've written all the references properly, we can commit
+	 * the packfile to make the changes effective */
+	if (error == GIT_SUCCESS) {
+		error = git_filebuf_commit(&pack_file);
+
+		/* when and only when the packfile has been properly written,
+		 * we can go ahead and remove the loose refs */
+		if (error == GIT_SUCCESS) {
+			struct stat st;
+
+			error = packed_remove_loose(repo, &packing_list);
+
+			if (gitfo_stat(pack_file_path, &st) == GIT_SUCCESS)
+				repo->references.packfile_time = st.st_mtime;
+		}
+	}
+	else git_filebuf_cleanup(&pack_file);
+
+	git_vector_free(&packing_list);
+
+	return error;
+}
+
+
+
+
+/*****************************************
+ * External Library API
+ *****************************************/
+
+/**
+ * Constructors
+ */
+int git_reference_lookup(git_reference **ref_out, git_repository *repo, const char *name)
+{
+	int error;
+	char normalized_name[GIT_PATH_MAX];
+
+	assert(ref_out && repo && name);
+
+	*ref_out = NULL;
+
+	error = normalize_name(normalized_name, name, 0);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	/* First, check has been previously loaded and cached */
+	*ref_out = git_hashtable_lookup(repo->references.loose_cache, normalized_name);
+	if (*ref_out != NULL)
+		return loose_update(*ref_out);
+
+	/* Then check if there is a loose file for that reference.*/
+	error = loose_lookup(ref_out, repo, normalized_name, 0);
+
+	/* If the file exists, we store it on the cache */
+	if (error == GIT_SUCCESS)
+		return git_hashtable_insert(repo->references.loose_cache, (*ref_out)->name, (*ref_out));
+
+	/* The loose lookup has failed, but not because the reference wasn't found;
+	 * probably the loose reference is corrupted. this is bad. */
+	if (error != GIT_ENOTFOUND)
+		return error;
+
+	/*
+	 * If we cannot find a loose reference, we look into the packfile
+	 * Load the packfile first if it hasn't been loaded 
+	 */
+	/* load all the packed references */
+	error = packed_load(repo);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	/* Look up on the packfile */
+	*ref_out = git_hashtable_lookup(repo->references.packfile, normalized_name);
+	if (*ref_out != NULL)
+		return GIT_SUCCESS;
+
+	/* The reference doesn't exist anywhere */
+	return GIT_ENOTFOUND;
+}
+
+int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target)
+{
+	char normalized[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
+	int error = GIT_SUCCESS;
+	git_reference *ref = NULL;
+
+	error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	/* The target can aither be the name of an object id reference or the name of another symbolic reference */
+	error = normalize_name(normalized, target, 0);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	/* set the target; this will write the reference on disk */
+	error = git_reference_set_target(ref, normalized);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = git_hashtable_insert(repo->references.loose_cache, ref->name, ref);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	*ref_out = ref;
+
+	return error;
+
+cleanup:
+	reference_free(ref);
+	return error;
+}
+
+int git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id)
+{
+	int error = GIT_SUCCESS;
+	git_reference *ref = NULL;
+
+	error = reference_create(&ref, repo, name, GIT_REF_OID);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	/* set the oid; this will write the reference on disk */
+	error = git_reference_set_oid(ref, id);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = git_hashtable_insert(repo->references.loose_cache, ref->name, ref);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	*ref_out = ref;
+
+	return error;
+
+cleanup:
+	reference_free(ref);
+	return error;
+}
+
+
+/**
+ * Getters
+ */
+git_rtype git_reference_type(git_reference *ref)
+{
+	assert(ref);
+
+	if (ref->type & GIT_REF_OID)
+		return GIT_REF_OID;
+
+	if (ref->type & GIT_REF_SYMBOLIC)
+		return GIT_REF_SYMBOLIC;
+
+	return GIT_REF_INVALID;
+}
+
+const char *git_reference_name(git_reference *ref)
+{
+	assert(ref);
+	return ref->name;
+}
+
+git_repository *git_reference_owner(git_reference *ref)
+{
+	assert(ref);
+	return ref->owner;
+}
+
+const git_oid *git_reference_oid(git_reference *ref)
+{
+	assert(ref);
+
+	if ((ref->type & GIT_REF_OID) == 0)
+		return NULL;
+
+	if (loose_update(ref) < GIT_SUCCESS)
+		return NULL;
+
+	return &((reference_oid *)ref)->oid;
+}
+
+const char *git_reference_target(git_reference *ref)
+{
+	assert(ref);
+
+	if ((ref->type & GIT_REF_SYMBOLIC) == 0)
+		return NULL;
+
+	if (loose_update(ref) < GIT_SUCCESS)
+		return NULL;
+
+	return ((reference_symbolic *)ref)->target;
+}
+
+/**
+ * Setters
+ */
+
+/*
+ * Change the OID target of a reference.
+ *
+ * For loose references, just change the oid in memory
+ * and overwrite the file in disk.
+ *
+ * For packed files, this is not pretty:
+ * For performance reasons, we write the new reference
+ * loose on disk (it replaces the old on the packfile),
+ * but we cannot invalidate the pointer to the reference,
+ * and most importantly, the `packfile` object must stay
+ * consistent with the representation of the packfile
+ * on disk. This is what we need to:
+ *
+ * 1. Copy the reference
+ * 2. Change the oid on the original
+ * 3. Write the original to disk
+ * 4. Write the original to the loose cache
+ * 5. Replace the original with the copy (old reference) in the packfile cache
+ */
+int git_reference_set_oid(git_reference *ref, const git_oid *id)
+{
+	reference_oid *ref_oid;
+	reference_oid *ref_old = NULL;
+	int error = GIT_SUCCESS;
+
+	if ((ref->type & GIT_REF_OID) == 0)
+		return GIT_EINVALIDREFSTATE;
+
+	ref_oid = (reference_oid *)ref;
+
+	/* duplicate the reference;
+	 * this copy will stay on the packfile cache */
+	if (ref->type & GIT_REF_PACKED) {
+		ref_old = git__malloc(sizeof(reference_oid));
+		if (ref_old == NULL)
+			return GIT_ENOMEM;
+
+		ref_old->ref.name = git__strdup(ref->name);
+		if (ref_old->ref.name == NULL) {
+			free(ref_old);
+			return GIT_ENOMEM;
+		}
+	}
+
+	git_oid_cpy(&ref_oid->oid, id);
+	ref->type &= ~GIT_REF_HAS_PEEL;
+
+	error = loose_write(ref); 
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	if (ref->type & GIT_REF_PACKED) {
+		/* insert the original on the loose cache */
+		error = git_hashtable_insert(ref->owner->references.loose_cache, ref->name, ref);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+
+		ref->type &= ~GIT_REF_PACKED;
+
+		/* replace the original in the packfile with the copy */
+		error = git_hashtable_insert(ref->owner->references.packfile, ref_old->ref.name, ref_old);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+	}
+
+	return GIT_SUCCESS;
+
+cleanup:
+	reference_free((git_reference *)ref_old);
+	return error;
+}
+
+/*
+ * Change the target of a symbolic reference.
+ *
+ * This is easy because symrefs cannot be inside
+ * a pack. We just change the target in memory
+ * and overwrite the file on disk.
+ */
+int git_reference_set_target(git_reference *ref, const char *target)
+{
+	reference_symbolic *ref_sym;
+
+	if ((ref->type & GIT_REF_SYMBOLIC) == 0)
+		return GIT_EINVALIDREFSTATE;
+
+	ref_sym = (reference_symbolic *)ref;
+
+	free(ref_sym->target);
+	ref_sym->target = git__strdup(target);
+	if (ref_sym->target == NULL)
+		return GIT_ENOMEM;
+
+	return loose_write(ref);
+}
+
+/**
+ * Other
+ */
+
+/*
+ * Delete a reference.
+ *
+ * If the reference is packed, this is an expensive
+ * operation. We need to remove the reference from
+ * the memory cache and then rewrite the whole pack
+ *
+ * If the reference is loose, we remove it on
+ * the filesystem and update the in-memory cache
+ * accordingly. We also make sure that an older version
+ * of it doesn't exist as a packed reference. If this
+ * is the case, this packed reference is removed as well.
+ *
+ * This obviously invalidates the `ref` pointer.
+ */
+int git_reference_delete(git_reference *ref)
+{
+	int error;
+	git_reference *reference;
+
+	assert(ref);
+
+	if (ref->type & GIT_REF_PACKED) {
+		git_hashtable_remove(ref->owner->references.packfile, ref->name);
+		error = packed_write(ref->owner);
+	} else {
+		char full_path[GIT_PATH_MAX];
+		git__joinpath(full_path, ref->owner->path_repository, ref->name);
+		git_hashtable_remove(ref->owner->references.loose_cache, ref->name);
+		error = gitfo_unlink(full_path);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+
+		/* When deleting a loose reference, we have to ensure that an older
+		 * packed version of it doesn't exist
+		 */
+		if (!git_reference_lookup(&reference, ref->owner, ref->name)) {
+			assert((reference->type & GIT_REF_PACKED) != 0);
+			error = git_reference_delete(reference);
+		}
+	}
+
+cleanup:
+	reference_free(ref);
+	return error;
+}
+
+/*
+ * Rename a reference
+ *
+ * If the reference is packed, we need to rewrite the
+ * packfile to remove the reference from it and create
+ * the reference back as a loose one.
+ *
+ * If the reference is loose, we just rename it on
+ * the filesystem.
+ *
+ * We also need to re-insert the reference on its corresponding
+ * in-memory cache, since the caches are indexed by refname.
+ */
+int git_reference_rename(git_reference *ref, const char *new_name)
+{
+	int error;
+	char *old_name;
+	char old_path[GIT_PATH_MAX], new_path[GIT_PATH_MAX], normalized_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
+	git_reference *looked_up_ref;
+
+	assert(ref);
+
+	/* Ensure the name is valid */
+	error = normalize_name(normalized_name, new_name, ref->type & GIT_REF_OID);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	/* Ensure we're not going to overwrite an existing reference */
+	error = git_reference_lookup(&looked_up_ref, ref->owner, new_name);
+	if (error == GIT_SUCCESS)
+		return GIT_EINVALIDREFNAME;
+
+	if (error != GIT_ENOTFOUND)
+		return error;
+
+
+	old_name = ref->name;
+	ref->name = git__strdup(new_name);
+
+	if (ref->name == NULL) {
+		ref->name = old_name;
+		return GIT_ENOMEM;
+	}
+
+	if (ref->type & GIT_REF_PACKED) {
+		/* write the packfile to disk; note
+		 * that the state of the in-memory cache is not
+		 * consistent, because the reference is indexed
+		 * by its old name but it already has the new one.
+		 * This doesn't affect writing, though, and allows
+		 * us to rollback if writing fails
+		 */
+
+		ref->type &= ~GIT_REF_PACKED;
+
+		/* Create the loose ref under its new name */
+		error = loose_write(ref);
+		if (error < GIT_SUCCESS) {
+			ref->type |= GIT_REF_PACKED;
+			goto cleanup;
+		}
+
+		/* Remove from the packfile cache in order to avoid packing it back
+		 * Note : we do not rely on git_reference_delete() because this would
+		 * invalidate the reference.
+		 */
+		git_hashtable_remove(ref->owner->references.packfile, old_name);
+
+		/* Recreate the packed-refs file without the reference */
+		error = packed_write(ref->owner);
+		if (error < GIT_SUCCESS)
+			goto rename_loose_to_old_name;
+
+	} else {
+		git__joinpath(old_path, ref->owner->path_repository, old_name);
+		git__joinpath(new_path, ref->owner->path_repository, ref->name);
+
+		error = gitfo_mv_force(old_path, new_path);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+
+		/* Once succesfully renamed, remove from the cache the reference known by its old name*/
+		git_hashtable_remove(ref->owner->references.loose_cache, old_name);
+	}
+
+	/* Store the renamed reference into the loose ref cache */
+	error = git_hashtable_insert(ref->owner->references.loose_cache, ref->name, ref);
+
+	free(old_name);
+	return error;
+
+cleanup:
+	/* restore the old name if this failed */
+	free(ref->name);
+	ref->name = old_name;
+	return error;
+
+rename_loose_to_old_name:
+	/* If we hit this point. Something *bad* happened! Think "Ghostbusters
+	 * crossing the streams" definition of bad.
+	 * Either the packed-refs has been correctly generated and something else
+	 * has gone wrong, or the writing of the new packed-refs has failed, and
+	 * we're stuck with the old one. As a loose ref always takes priority over
+	 * a packed ref, we'll eventually try and rename the generated loose ref to
+	 * its former name. It even that fails, well... we might have lost the reference
+	 * for good. :-/
+	*/
+
+	git__joinpath(old_path, ref->owner->path_repository, ref->name);
+	git__joinpath(new_path, ref->owner->path_repository, old_name);
+
+	/* No error checking. We'll return the initial error */
+	gitfo_mv_force(old_path, new_path);
+
+	/* restore the old name */
+	free(ref->name);
+	ref->name = old_name;
+
+	return error;
+}
+
+int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
+{
+	git_repository *repo;
+	int error, i;
+
+	assert(resolved_ref && ref);
+	*resolved_ref = NULL;
+
+	if ((error = loose_update(ref)) < GIT_SUCCESS)
+		return error;
+	
+	repo = ref->owner;
+
+	for (i = 0; i < MAX_NESTING_LEVEL; ++i) {
+		reference_symbolic *ref_sym;
+
+		if (ref->type & GIT_REF_OID) {
+			*resolved_ref = ref;
+			return GIT_SUCCESS;
+		}
+
+		ref_sym = (reference_symbolic *)ref;
+		if ((error = git_reference_lookup(&ref, repo, ref_sym->target)) < GIT_SUCCESS)
+			return error;
+	}
+
+	return GIT_ETOONESTEDSYMREF;
+}
+
+int git_reference_packall(git_repository *repo)
+{
+	int error;
+
+	/* load the existing packfile */
+	if ((error = packed_load(repo)) < GIT_SUCCESS)
+		return error;
+
+	/* update it in-memory with all the loose references */
+	if ((error = packed_loadloose(repo)) < GIT_SUCCESS)
+		return error;
+
+	/* write it back to disk */
+	return packed_write(repo);
+}
+
+int git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags)
+{
+	int error;
+	struct dirent_list_data data;
+	char refs_path[GIT_PATH_MAX];
+
+	array->strings = NULL;
+	array->count = 0;
+
+	git_vector_init(&data.ref_list, 8, NULL);
+	data.repo_path_len = strlen(repo->path_repository);
+	data.list_flags = list_flags;
+	data.repo = repo;
+
+	/* list all the packed references first */
+	if (list_flags & GIT_REF_PACKED) {
+		const char *ref_name;
+		void *_unused;
+
+		if ((error = packed_load(repo)) < GIT_SUCCESS) {
+			git_vector_free(&data.ref_list);
+			return error;
+		}
+
+		GIT_HASHTABLE_FOREACH(repo->references.packfile, ref_name, _unused,
+			git_vector_insert(&data.ref_list, git__strdup(ref_name));
+		);
+	}
+
+	/* now list the loose references, trying not to
+	 * duplicate the ref names already in the packed-refs file */
+	git__joinpath(refs_path, repo->path_repository, GIT_REFS_DIR);
+	error = gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
+
+	if (error < GIT_SUCCESS) {
+		git_vector_free(&data.ref_list);
+		return error;
+	}
+
+	array->strings = (char **)data.ref_list.contents;
+	array->count = data.ref_list.length;
+	return GIT_SUCCESS;
+}
+
+
+
+
+/*****************************************
+ * Init/free (repository API)
+ *****************************************/
+int git_repository__refcache_init(git_refcache *refs)
+{
+	assert(refs);
+
+	refs->loose_cache = git_hashtable_alloc(
+		default_table_size,
+		reftable_hash,
+		(git_hash_keyeq_ptr)strcmp);
+
+	/* packfile loaded lazily */
+	refs->packfile = NULL;
+
+	return (refs->loose_cache) ? GIT_SUCCESS : GIT_ENOMEM;
+}
+
+void git_repository__refcache_free(git_refcache *refs)
+{
+	git_reference *reference;
+	const void *_unused;
+
+	assert(refs);
+
+	GIT_HASHTABLE_FOREACH(refs->loose_cache, _unused, reference,
+		reference_free(reference);
+	);
+
+	git_hashtable_free(refs->loose_cache);
+
+	if (refs->packfile) {
+		GIT_HASHTABLE_FOREACH(refs->packfile, _unused, reference,
+			reference_free(reference);
+		);
+
+		git_hashtable_free(refs->packfile);
+	}
+}
+
+
+
+/*****************************************
+ * Name normalization
+ *****************************************/
+static int check_valid_ref_char(char ch)
+{
+	if (ch <= ' ')
+		return GIT_ERROR;
+
+	switch (ch) {
+	case '~':
+	case '^':
+	case ':':
+	case '\\':
+	case '?':
+	case '[':
+	case '*':
+		return GIT_ERROR;
+		break;
+
+	default:
+		return GIT_SUCCESS;
+	}
+}
+
+static int normalize_name(char *buffer_out, const char *name, int is_oid_ref)
+{
+	int error = GIT_SUCCESS;
+	const char *name_end, *buffer_out_start;
+	char *current;
+	int contains_a_slash = 0;
+
+	assert(name && buffer_out);
+
+	buffer_out_start = buffer_out;
+	current = (char *)name;
+	name_end = name + strlen(name);
+
+	/* A refname can not be empty */
+	if (name_end == name)
+		return GIT_EINVALIDREFNAME;
+
+	/* A refname can not end with a dot or a slash */
+	if (*(name_end - 1) == '.' || *(name_end - 1) == '/')
+		return GIT_EINVALIDREFNAME;
+
+	while (current < name_end) {
+		if (check_valid_ref_char(*current))
+				return GIT_EINVALIDREFNAME;
+
+		if (buffer_out > buffer_out_start) {
+			char prev = *(buffer_out - 1);
+
+			/* A refname can not start with a dot nor contain a double dot */
+			if (*current == '.' && ((prev == '.') || (prev == '/')))
+				return GIT_EINVALIDREFNAME;
+
+			/* '@{' is forbidden within a refname */
+			if (*current == '{' && prev == '@')
+				return GIT_EINVALIDREFNAME;
+
+			/* Prevent multiple slashes from being added to the output */
+			if (*current == '/' && prev == '/') {
+				current++;
+				continue;
+			}
+		}
+
+		if (*current == '/')
+			contains_a_slash = 1;
+
+		*buffer_out++ = *current++;
+	}
+
+	/* Object id refname have to contain at least one slash */
+	if (is_oid_ref && !contains_a_slash)
+				return GIT_EINVALIDREFNAME;
+
+	/* A refname can not end with ".lock" */
+	if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
+				return GIT_EINVALIDREFNAME;
+
+	*buffer_out = '\0';
+
+	/* For object id references, name has to start with refs/(heads|tags|remotes) */
+	if (is_oid_ref && !(!git__prefixcmp(buffer_out_start, GIT_REFS_HEADS_DIR) ||
+			!git__prefixcmp(buffer_out_start, GIT_REFS_TAGS_DIR) || !git__prefixcmp(buffer_out_start, GIT_REFS_REMOTES_DIR)))
+		return GIT_EINVALIDREFNAME;
+
+	return error;
+}
+
+int git_reference__normalize_name(char *buffer_out, const char *name)
+{
+	return normalize_name(buffer_out, name, 0);
+}
+
+int git_reference__normalize_name_oid(char *buffer_out, const char *name)
+{
+	return normalize_name(buffer_out, name, 1);
+}
+
+
diff --git a/libgit2/src/refs.h b/libgit2/src/refs.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/refs.h
@@ -0,0 +1,42 @@
+#ifndef INCLUDE_refs_h__
+#define INCLUDE_refs_h__
+
+#include "common.h"
+#include "git2/oid.h"
+#include "git2/refs.h"
+#include "hashtable.h"
+
+#define GIT_REFS_DIR "refs/"
+#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
+#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
+#define GIT_REFS_REMOTES_DIR GIT_REFS_DIR "remotes/"
+
+#define GIT_SYMREF "ref: "
+#define GIT_PACKEDREFS_FILE "packed-refs"
+#define GIT_PACKEDREFS_HEADER "# pack-refs with: peeled "
+#define MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH 100
+
+#define GIT_HEAD_FILE "HEAD"
+#define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master"
+
+struct git_reference {
+	git_repository *owner;
+	char *name;
+	unsigned int type;
+	time_t mtime;
+};
+
+typedef struct {
+	git_hashtable *packfile;
+	git_hashtable *loose_cache;
+	time_t packfile_time;
+} git_refcache;
+
+
+void git_repository__refcache_free(git_refcache *refs);
+int git_repository__refcache_init(git_refcache *refs);
+
+int git_reference__normalize_name(char *buffer_out, const char *name);
+int git_reference__normalize_name_oid(char *buffer_out, const char *name);
+
+#endif
diff --git a/libgit2/src/repository.c b/libgit2/src/repository.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/repository.c
@@ -0,0 +1,541 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <stdarg.h>
+
+#include "git2/object.h"
+
+#include "common.h"
+#include "repository.h"
+#include "commit.h"
+#include "tag.h"
+#include "blob.h"
+#include "fileops.h"
+
+#include "refs.h"
+
+#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
+#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
+
+#define GIT_BRANCH_MASTER "master"
+
+static const int OBJECT_TABLE_SIZE = 32;
+
+typedef struct {
+	char *path_repository;
+	unsigned is_bare:1, has_been_reinit:1;
+} repo_init;
+
+/*
+ * Hash table methods
+ *
+ * Callbacks for the ODB cache, implemented
+ * as a hash table
+ */
+static uint32_t object_table_hash(const void *key, int hash_id)
+{
+	uint32_t r;
+	git_oid *id;
+
+	id = (git_oid *)key;
+	memcpy(&r, id->id + (hash_id * sizeof(uint32_t)), sizeof(r));
+	return r;
+}
+
+/*
+ * Git repository open methods
+ *
+ * Open a repository object from its path
+ */
+static int assign_repository_dirs(
+		git_repository *repo,
+		const char *git_dir,
+		const char *git_object_directory,
+		const char *git_index_file,
+		const char *git_work_tree)
+{
+	char path_aux[GIT_PATH_MAX];
+	size_t git_dir_path_len;
+	int error = GIT_SUCCESS;
+
+	assert(repo);
+
+	if (git_dir == NULL)
+		return GIT_ENOTFOUND;
+
+	error = gitfo_prettify_dir_path(path_aux, git_dir);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	git_dir_path_len = strlen(path_aux);
+
+	/* store GIT_DIR */
+	repo->path_repository = git__strdup(path_aux);
+	if (repo->path_repository == NULL)
+		return GIT_ENOMEM;
+
+	/* path to GIT_OBJECT_DIRECTORY */
+	if (git_object_directory == NULL)
+		git__joinpath(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
+	else {
+		error = gitfo_prettify_dir_path(path_aux, git_object_directory);
+		if (error < GIT_SUCCESS)
+			return error;
+	}
+
+	/* Store GIT_OBJECT_DIRECTORY */
+	repo->path_odb = git__strdup(path_aux);
+	if (repo->path_odb == NULL)
+		return GIT_ENOMEM;
+
+	/* path to GIT_WORK_TREE */
+	if (git_work_tree == NULL)
+		repo->is_bare = 1;
+	else {
+		error = gitfo_prettify_dir_path(path_aux, git_work_tree);
+		if (error < GIT_SUCCESS)
+			return error;
+
+		/* Store GIT_WORK_TREE */
+		repo->path_workdir = git__strdup(path_aux);
+		if (repo->path_workdir == NULL)
+			return GIT_ENOMEM;
+
+		/* Path to GIT_INDEX_FILE */
+		if (git_index_file == NULL)
+			git__joinpath(path_aux, repo->path_repository, GIT_INDEX_FILE);
+		else {
+			error = gitfo_prettify_file_path(path_aux, git_index_file);
+			if (error < GIT_SUCCESS)
+				return error;
+		}
+
+		/* store GIT_INDEX_FILE */
+		repo->path_index = git__strdup(path_aux);
+		if (repo->path_index == NULL)
+			return GIT_ENOMEM;
+	}
+	
+	return GIT_SUCCESS;
+}
+
+static int check_repository_dirs(git_repository *repo)
+{
+	char path_aux[GIT_PATH_MAX];
+
+	if (gitfo_isdir(repo->path_repository) < GIT_SUCCESS)
+		return GIT_ENOTAREPO;
+
+	/* Ensure GIT_OBJECT_DIRECTORY exists */
+	if (gitfo_isdir(repo->path_odb) < GIT_SUCCESS)
+		return GIT_ENOTAREPO;
+
+	/* Ensure HEAD file exists */
+	git__joinpath(path_aux, repo->path_repository, GIT_HEAD_FILE);
+	if (gitfo_exists(path_aux) < 0)
+		return GIT_ENOTAREPO;
+
+	return GIT_SUCCESS;
+}
+
+static int guess_repository_dirs(git_repository *repo, const char *repository_path)
+{
+	char buffer[GIT_PATH_MAX];
+	const char *path_work_tree = NULL;
+
+	/* Git directory name */
+	if (git__basename_r(buffer, sizeof(buffer), repository_path) < 0)
+		return GIT_EINVALIDPATH;
+
+	if (strcmp(buffer, DOT_GIT) == 0) {
+		/* Path to working dir */
+		if (git__dirname_r(buffer, sizeof(buffer), repository_path) < 0)
+			return GIT_EINVALIDPATH;
+		path_work_tree = buffer;
+	}
+
+	return assign_repository_dirs(repo, repository_path, NULL, NULL, path_work_tree);
+}
+
+static git_repository *repository_alloc()
+{
+	git_repository *repo = git__malloc(sizeof(git_repository));
+	if (!repo)
+		return NULL;
+
+	memset(repo, 0x0, sizeof(git_repository));
+
+	repo->objects = git_hashtable_alloc(
+			OBJECT_TABLE_SIZE, 
+			object_table_hash,
+			(git_hash_keyeq_ptr)git_oid_cmp);
+
+	if (repo->objects == NULL) { 
+		free(repo);
+		return NULL;
+	}
+
+	if (git_repository__refcache_init(&repo->references) < GIT_SUCCESS) {
+		git_hashtable_free(repo->objects);
+		free(repo);
+		return NULL;
+	}
+
+	if (git_vector_init(&repo->memory_objects, 16, NULL) < GIT_SUCCESS) {
+		git_hashtable_free(repo->objects);
+		git_repository__refcache_free(&repo->references);
+		free(repo);
+		return NULL;
+	}
+
+	return repo;
+}
+
+static int init_odb(git_repository *repo)
+{
+	return git_odb_open(&repo->db, repo->path_odb);
+}
+
+int git_repository_open3(git_repository **repo_out,
+		const char *git_dir,
+		git_odb *object_database,
+		const char *git_index_file,
+		const char *git_work_tree)
+{
+	git_repository *repo;
+	int error = GIT_SUCCESS;
+
+	assert(repo_out);
+
+	if (object_database == NULL)
+		return GIT_ERROR;
+
+	repo = repository_alloc();
+	if (repo == NULL)
+		return GIT_ENOMEM;
+
+	error = assign_repository_dirs(repo, 
+			git_dir, 
+			NULL,
+			git_index_file,
+			git_work_tree);
+
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = check_repository_dirs(repo);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	repo->db = object_database;
+
+	*repo_out = repo;
+	return GIT_SUCCESS;
+
+cleanup:
+	git_repository_free(repo);
+	return error;
+}
+
+
+int git_repository_open2(git_repository **repo_out,
+		const char *git_dir,
+		const char *git_object_directory,
+		const char *git_index_file,
+		const char *git_work_tree)
+{
+	git_repository *repo;
+	int error = GIT_SUCCESS;
+
+	assert(repo_out);
+
+	repo = repository_alloc();
+	if (repo == NULL)
+		return GIT_ENOMEM;
+
+	error = assign_repository_dirs(repo,
+			git_dir, 
+			git_object_directory,
+			git_index_file,
+			git_work_tree);
+
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = check_repository_dirs(repo);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = init_odb(repo);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	*repo_out = repo;
+	return GIT_SUCCESS;
+
+cleanup:
+	git_repository_free(repo);
+	return error;
+}
+
+int git_repository_open(git_repository **repo_out, const char *path)
+{
+	git_repository *repo;
+	int error = GIT_SUCCESS;
+
+	assert(repo_out && path);
+
+	repo = repository_alloc();
+	if (repo == NULL)
+		return GIT_ENOMEM;
+
+	error = guess_repository_dirs(repo, path);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = check_repository_dirs(repo);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = init_odb(repo);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	*repo_out = repo;
+	return GIT_SUCCESS;
+
+cleanup:
+	git_repository_free(repo);
+	return error;
+}
+
+int git_repository_gc(git_repository *repo)
+{
+	int collected = 0;
+	git_object *object;
+	const void *_unused;
+
+	GIT_HASHTABLE_FOREACH(repo->objects, _unused, object,
+		if (object->can_free) {
+			git_object__free(object);
+			collected++;
+		}
+	);
+
+	return collected;
+}
+
+void git_repository_free(git_repository *repo)
+{
+	git_object *object;
+	const void *_unused;
+	unsigned int i;
+
+	if (repo == NULL)
+		return;
+
+	/* force free all the objects */
+	GIT_HASHTABLE_FOREACH(repo->objects, _unused, object,
+		git_object__free(object);
+	);
+
+	for (i = 0; i < repo->memory_objects.length; ++i) {
+		object = git_vector_get(&repo->memory_objects, i);
+		git_object__free(object);
+	}
+
+	free(repo->path_workdir);
+	free(repo->path_index);
+	free(repo->path_repository);
+	free(repo->path_odb);
+
+	git_hashtable_free(repo->objects);
+	git_vector_free(&repo->memory_objects);
+
+	git_repository__refcache_free(&repo->references);
+
+	if (repo->db != NULL)
+		git_odb_close(repo->db);
+
+	if (repo->index != NULL)
+		git_index_free(repo->index);
+
+	free(repo);
+}
+
+int git_repository_index(git_index **index_out, git_repository *repo)
+{
+	int error;
+
+	assert(index_out && repo);
+
+	if (repo->index == NULL) {
+		error = git_index_open_inrepo(&repo->index, repo);
+		if (error < GIT_SUCCESS)
+			return error;
+
+		assert(repo->index != NULL);
+	}
+
+	*index_out = repo->index;
+	return GIT_SUCCESS;
+}
+
+git_odb *git_repository_database(git_repository *repo)
+{
+	assert(repo);
+	return repo->db;
+}
+
+static int repo_init_reinit(repo_init *results)
+{
+	/* TODO: reinit the repository */
+	results->has_been_reinit = 1;
+	return GIT_SUCCESS;
+}
+
+static int repo_init_createhead(git_repository *repo)
+{
+	git_reference *head_reference;
+	return  git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE);
+}
+
+static int repo_init_check_head_existence(char * repository_path)
+{
+	char temp_path[GIT_PATH_MAX];
+
+	git__joinpath(temp_path, repository_path, GIT_HEAD_FILE);
+	return gitfo_exists(temp_path);
+}
+
+static int repo_init_structure(repo_init *results)
+{
+	const int mode = 0755; /* or 0777 ? */
+
+	char temp_path[GIT_PATH_MAX];
+	char *git_dir = results->path_repository;
+
+	if (gitfo_mkdir_recurs(git_dir, mode))
+		return GIT_ERROR;
+
+	/* Creates the '/objects/info/' directory */
+	git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
+	if (gitfo_mkdir_recurs(temp_path, mode) < GIT_SUCCESS)
+		return GIT_ERROR;
+
+	/* Creates the '/objects/pack/' directory */
+	git__joinpath(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
+	if (gitfo_mkdir(temp_path, mode))
+		return GIT_ERROR;
+
+	/* Creates the '/refs/heads/' directory */
+	git__joinpath(temp_path, git_dir, GIT_REFS_HEADS_DIR);
+	if (gitfo_mkdir_recurs(temp_path, mode))
+		return GIT_ERROR;
+
+	/* Creates the '/refs/tags/' directory */
+	git__joinpath(temp_path, git_dir, GIT_REFS_TAGS_DIR);
+	if (gitfo_mkdir(temp_path, mode))
+		return GIT_ERROR;
+
+	/* TODO: what's left? templates? */
+
+	return GIT_SUCCESS;
+}
+
+static int repo_init_find_dir(repo_init *results, const char* path)
+{
+	char temp_path[GIT_PATH_MAX];
+	int error = GIT_SUCCESS;
+
+	error = gitfo_prettify_dir_path(temp_path, path);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	if (!results->is_bare) {
+		git__joinpath(temp_path, temp_path, GIT_DIR);
+	}
+
+	results->path_repository = git__strdup(temp_path);
+	if (results->path_repository == NULL)
+		return GIT_ENOMEM;
+
+	return GIT_SUCCESS;
+}
+
+int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare)
+{
+	int error = GIT_SUCCESS;
+	git_repository *repo = NULL;
+	repo_init results;
+	
+	assert(repo_out && path);
+
+	results.path_repository = NULL;
+	results.is_bare = is_bare;
+
+	error = repo_init_find_dir(&results, path);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	if (!repo_init_check_head_existence(results.path_repository))
+		return repo_init_reinit(&results);
+
+	error = repo_init_structure(&results);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	repo = repository_alloc();
+	if (repo == NULL) {
+		error = GIT_ENOMEM;
+		goto cleanup;
+	}
+
+	error = guess_repository_dirs(repo, results.path_repository);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	assert(repo->is_bare == is_bare);
+
+	error = init_odb(repo);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	error = repo_init_createhead(repo);
+	if (error < GIT_SUCCESS)
+		goto cleanup;
+
+	/* should never fail */
+	assert(check_repository_dirs(repo) == GIT_SUCCESS);
+
+	free(results.path_repository);
+	*repo_out = repo;
+	return GIT_SUCCESS;
+
+cleanup:
+	free(results.path_repository);
+	git_repository_free(repo);
+	return error;
+}
+
diff --git a/libgit2/src/repository.h b/libgit2/src/repository.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/repository.h
@@ -0,0 +1,65 @@
+#ifndef INCLUDE_repository_h__
+#define INCLUDE_repository_h__
+
+#include "git2/common.h"
+#include "git2/oid.h"
+#include "git2/odb.h"
+#include "git2/repository.h"
+#include "git2/object.h"
+
+#include "hashtable.h"
+#include "index.h"
+#include "refs.h"
+
+#define DOT_GIT ".git"
+#define GIT_DIR DOT_GIT "/"
+#define GIT_OBJECTS_DIR "objects/"
+#define GIT_INDEX_FILE "index"
+
+typedef struct {
+	git_rawobj raw;
+	void *write_ptr;
+	size_t written_bytes;
+	int open:1;
+} git_odb_source;
+
+struct git_object {
+	git_oid id;
+	git_repository *repo;
+	git_odb_source source;
+	unsigned int lru;
+	unsigned char in_memory, modified, can_free, _pad;
+};
+
+struct git_repository {
+	git_odb *db;
+	git_index *index;
+
+	git_hashtable *objects;
+	git_vector memory_objects;
+
+	git_refcache references;
+
+	char *path_repository;
+	char *path_index;
+	char *path_odb;
+	char *path_workdir;
+
+	unsigned is_bare:1;
+	unsigned int lru_counter;
+};
+
+int git_object__source_open(git_object *object);
+void git_object__source_close(git_object *object);
+
+/* fully free the object; internal method, do not
+ * export */
+void git_object__free(git_object *object);
+
+int git__source_printf(git_odb_source *source, const char *format, ...);
+int git__source_write(git_odb_source *source, const void *bytes, size_t len);
+
+int git__parse_oid(git_oid *oid, char **buffer_out, const char *buffer_end, const char *header);
+int git__write_oid(git_odb_source *src, const char *header, const git_oid *oid);
+
+#endif
diff --git a/libgit2/src/revwalk.c b/libgit2/src/revwalk.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/revwalk.c
@@ -0,0 +1,565 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "commit.h"
+#include "hashtable.h"
+#include "pqueue.h"
+
+#include "git2/revwalk.h"
+
+typedef struct commit_object {
+	git_oid oid;
+	uint32_t time;
+	unsigned int seen:1,
+			 uninteresting:1,
+			 topo_delay:1,
+			 parsed:1;
+
+	unsigned short in_degree;
+	unsigned short out_degree;
+
+	struct commit_object **parents;
+} commit_object;
+
+typedef struct commit_list {
+	commit_object *item;
+	struct commit_list *next;
+} commit_list;
+
+struct git_revwalk {
+	git_repository *repo;
+
+	git_hashtable *commits;
+
+	commit_list *iterator_topo;
+	commit_list *iterator_rand;
+	commit_list *iterator_reverse;
+	git_pqueue iterator_time;
+
+	int (*get_next)(commit_object **, git_revwalk *);
+	int (*enqueue)(git_revwalk *, commit_object *);
+
+	git_vector memory_alloc;
+	size_t chunk_size;
+
+	unsigned walking:1;
+	unsigned int sorting;
+};
+
+commit_list *commit_list_insert(commit_object *item, commit_list **list_p)
+{
+	commit_list *new_list = git__malloc(sizeof(commit_list));
+	new_list->item = item;
+	new_list->next = *list_p;
+	*list_p = new_list;
+	return new_list;
+}
+
+void commit_list_free(commit_list **list_p)
+{
+	commit_list *list = *list_p;
+
+	while (list) {
+		commit_list *temp = list;
+		list = temp->next;
+		free(temp);
+	}
+
+	*list_p = NULL;
+}
+
+commit_object *commit_list_pop(commit_list **stack)
+{
+	commit_list *top = *stack;
+	commit_object *item = top ? top->item : NULL;
+
+	if (top) {
+		*stack = top->next;
+		free(top);
+	}
+	return item;
+}
+
+static int commit_time_cmp(void *a, void *b)
+{
+	commit_object *commit_a = (commit_object *)a;
+	commit_object *commit_b = (commit_object *)b;
+
+	return (commit_a->time < commit_b->time);
+}
+
+static uint32_t object_table_hash(const void *key, int hash_id)
+{
+	uint32_t r;
+	git_oid *id;
+
+	id = (git_oid *)key;
+	memcpy(&r, id->id + (hash_id * sizeof(uint32_t)), sizeof(r));
+	return r;
+}
+
+#define COMMITS_PER_CHUNK 128
+#define CHUNK_STEP 64
+#define PARENTS_PER_COMMIT ((CHUNK_STEP - sizeof(commit_object)) / sizeof(commit_object *))
+
+static int alloc_chunk(git_revwalk *walk)
+{
+	void *chunk;
+
+	chunk = git__calloc(COMMITS_PER_CHUNK, CHUNK_STEP);
+	if (chunk == NULL)
+		return GIT_ENOMEM;
+
+	walk->chunk_size = 0;
+	return git_vector_insert(&walk->memory_alloc, chunk);
+}
+
+static commit_object *alloc_commit(git_revwalk *walk)
+{
+	unsigned char *chunk;
+
+	if (walk->chunk_size == COMMITS_PER_CHUNK)
+		alloc_chunk(walk);
+
+	chunk = git_vector_get(&walk->memory_alloc, walk->memory_alloc.length - 1);
+	chunk += (walk->chunk_size * CHUNK_STEP);
+	walk->chunk_size++;
+
+	return (commit_object *)chunk;
+}
+
+static commit_object **alloc_parents(commit_object *commit, size_t n_parents)
+{
+	if (n_parents <= PARENTS_PER_COMMIT)
+		return (commit_object **)((unsigned char *)commit + sizeof(commit_object));
+
+	return git__malloc(n_parents * sizeof(commit_object *));
+}
+
+
+static commit_object *commit_lookup(git_revwalk *walk, const git_oid *oid)
+{
+	commit_object *commit;
+
+	if ((commit = git_hashtable_lookup(walk->commits, oid)) != NULL)
+		return commit;
+
+	commit = alloc_commit(walk);
+	if (commit == NULL)
+		return NULL;
+
+	git_oid_cpy(&commit->oid, oid);
+
+	if (git_hashtable_insert(walk->commits, &commit->oid, commit) < GIT_SUCCESS) {
+		free(commit);
+		return NULL;
+	}
+
+	return commit;
+}
+
+static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawobj *raw)
+{
+	const int parent_len = STRLEN("parent ") + GIT_OID_HEXSZ + 1;
+
+	unsigned char *buffer = raw->data;
+	unsigned char *buffer_end = buffer + raw->len;
+	unsigned char *parents_start;
+
+	int i, parents = 0;
+
+	buffer += STRLEN("tree ") + GIT_OID_HEXSZ + 1;
+
+	parents_start = buffer;
+	while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", STRLEN("parent ")) == 0) {
+		parents++;
+		buffer += parent_len;
+	}
+
+	commit->parents = alloc_parents(commit, parents);
+	if (commit->parents == NULL)
+		return GIT_ENOMEM;
+
+	buffer = parents_start;
+	for (i = 0; i < parents; ++i) {
+		git_oid oid;
+
+		if (git_oid_mkstr(&oid, (char *)buffer + STRLEN("parent ")) < GIT_SUCCESS)
+			return GIT_EOBJCORRUPTED;
+
+		commit->parents[i] = commit_lookup(walk, &oid);
+		if (commit->parents[i] == NULL)
+			return GIT_ENOMEM;
+
+		buffer += parent_len;
+	}
+
+	commit->out_degree = (unsigned short)parents;
+
+	if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
+		return GIT_EOBJCORRUPTED;
+
+	buffer = memchr(buffer, '>', buffer_end - buffer);
+	if (buffer == NULL)
+		return GIT_EOBJCORRUPTED;
+
+	commit->time = strtol((char *)buffer + 2, NULL, 10);
+	if (commit->time == 0)
+		return GIT_EOBJCORRUPTED;
+
+	commit->parsed = 1;
+	return GIT_SUCCESS;
+}
+
+static int commit_parse(git_revwalk *walk, commit_object *commit)
+{
+	git_rawobj data;
+	int error;
+
+	if (commit->parsed)
+		return GIT_SUCCESS;
+
+	if ((error = git_odb_read(&data, walk->repo->db, &commit->oid)) < GIT_SUCCESS)
+		return error;
+
+	if (data.type != GIT_OBJ_COMMIT) {
+		git_rawobj_close(&data);
+		return GIT_EOBJTYPE;
+	}
+
+	error = commit_quick_parse(walk, commit, &data);
+	git_rawobj_close(&data);
+	return error;
+}
+
+static void mark_uninteresting(commit_object *commit)
+{
+	unsigned short i;
+	assert(commit);
+
+	commit->uninteresting = 1;
+
+	for (i = 0; i < commit->out_degree; ++i)
+		if (!commit->parents[i]->uninteresting)
+			mark_uninteresting(commit->parents[i]);
+}
+
+static int process_commit(git_revwalk *walk, commit_object *commit)
+{
+	int error;
+
+	if (commit->seen)
+		return GIT_SUCCESS;
+
+	commit->seen = 1;
+
+	if ((error = commit_parse(walk, commit)) < GIT_SUCCESS)
+			return error;
+
+	if (commit->uninteresting)
+		mark_uninteresting(commit);
+
+	return walk->enqueue(walk, commit);
+}
+
+static int process_commit_parents(git_revwalk *walk, commit_object *commit)
+{
+	unsigned short i;
+	int error = GIT_SUCCESS;
+
+	for (i = 0; i < commit->out_degree && error == GIT_SUCCESS; ++i) {
+		error = process_commit(walk, commit->parents[i]);
+	}
+
+	return error;
+}
+
+static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
+{
+	commit_object *commit;
+
+	commit = commit_lookup(walk, oid);
+	if (commit == NULL)
+		return GIT_ENOTFOUND;
+
+	commit->uninteresting = uninteresting;
+
+	return process_commit(walk, commit);
+}
+
+int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
+{
+	assert(walk && oid);
+	return push_commit(walk, oid, 0);
+}
+
+int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
+{
+	assert(walk && oid);
+	return push_commit(walk, oid, 1);
+}
+
+static int revwalk_enqueue_timesort(git_revwalk *walk, commit_object *commit)
+{
+	return git_pqueue_insert(&walk->iterator_time, commit);
+}
+
+static int revwalk_enqueue_unsorted(git_revwalk *walk, commit_object *commit)
+{
+	return commit_list_insert(commit, &walk->iterator_rand) ? GIT_SUCCESS : GIT_ENOMEM;
+}
+
+static int revwalk_next_timesort(commit_object **object_out, git_revwalk *walk)
+{
+	int error;
+	commit_object *next;
+
+	while ((next = git_pqueue_pop(&walk->iterator_time)) != NULL) {
+		if ((error = process_commit_parents(walk, next)) < GIT_SUCCESS)
+			return error;
+
+		if (!next->uninteresting) {
+			*object_out = next;
+			return GIT_SUCCESS;
+		}
+	}
+
+	return GIT_EREVWALKOVER;
+}
+
+static int revwalk_next_unsorted(commit_object **object_out, git_revwalk *walk)
+{
+	int error;
+	commit_object *next;
+
+	while ((next = commit_list_pop(&walk->iterator_rand)) != NULL) {
+		if ((error = process_commit_parents(walk, next)) < GIT_SUCCESS)
+			return error;
+
+		if (!next->uninteresting) {
+			*object_out = next;
+			return GIT_SUCCESS;
+		}
+	}
+
+	return GIT_EREVWALKOVER;
+}
+
+static int revwalk_next_toposort(commit_object **object_out, git_revwalk *walk)
+{
+	commit_object *next;
+	unsigned short i;
+
+	for (;;) {
+		next = commit_list_pop(&walk->iterator_topo);
+		if (next == NULL)
+			return GIT_EREVWALKOVER;
+
+		if (next->in_degree > 0) {
+			next->topo_delay = 1;
+			continue;
+		}
+
+		for (i = 0; i < next->out_degree; ++i) {
+			commit_object *parent = next->parents[i];
+
+			if (--parent->in_degree == 0 && parent->topo_delay) {
+				parent->topo_delay = 0;
+				commit_list_insert(parent, &walk->iterator_topo);
+			}
+		}
+
+		*object_out = next;
+		return GIT_SUCCESS;
+	}
+}
+
+static int revwalk_next_reverse(commit_object **object_out, git_revwalk *walk)
+{
+	*object_out = commit_list_pop(&walk->iterator_reverse);
+	return *object_out ? GIT_SUCCESS : GIT_EREVWALKOVER;
+}
+
+
+static int prepare_walk(git_revwalk *walk)
+{
+	int error;
+	commit_object *next;
+
+	if (walk->sorting & GIT_SORT_TOPOLOGICAL) {
+		unsigned short i;
+
+		while ((error = walk->get_next(&next, walk)) == GIT_SUCCESS) {
+			for (i = 0; i < next->out_degree; ++i) {
+				commit_object *parent = next->parents[i];
+				parent->in_degree++;
+			}
+
+			commit_list_insert(next, &walk->iterator_topo);
+		}
+
+		if (error != GIT_EREVWALKOVER)
+			return error;
+
+		walk->get_next = &revwalk_next_toposort;
+	}
+
+	if (walk->sorting & GIT_SORT_REVERSE) {
+
+		while ((error = walk->get_next(&next, walk)) == GIT_SUCCESS)
+			commit_list_insert(next, &walk->iterator_reverse);
+
+		if (error != GIT_EREVWALKOVER)
+			return error;
+
+		walk->get_next = &revwalk_next_reverse;
+	}
+
+	walk->walking = 1;
+	return GIT_SUCCESS;
+}
+
+
+
+
+
+int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
+{
+	git_revwalk *walk;
+
+	walk = git__malloc(sizeof(git_revwalk));
+	if (walk == NULL)
+		return GIT_ENOMEM;
+
+	memset(walk, 0x0, sizeof(git_revwalk));
+
+	walk->commits = git_hashtable_alloc(64,
+			object_table_hash,
+			(git_hash_keyeq_ptr)git_oid_cmp);
+
+	if (walk->commits == NULL) {
+		free(walk);
+		return GIT_ENOMEM;
+	}
+
+	git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp);
+	git_vector_init(&walk->memory_alloc, 8, NULL);
+	alloc_chunk(walk);
+
+	walk->get_next = &revwalk_next_unsorted;
+	walk->enqueue = &revwalk_enqueue_unsorted;
+
+	walk->repo = repo;
+
+	*revwalk_out = walk;
+	return GIT_SUCCESS;
+}
+
+void git_revwalk_free(git_revwalk *walk)
+{
+	unsigned int i;
+
+	if (walk == NULL)
+		return;
+
+	git_revwalk_reset(walk);
+	git_hashtable_free(walk->commits);
+	git_pqueue_free(&walk->iterator_time);
+
+	for (i = 0; i < walk->memory_alloc.length; ++i)
+		free(git_vector_get(&walk->memory_alloc, i));
+
+	git_vector_free(&walk->memory_alloc);
+	free(walk);
+}
+
+git_repository *git_revwalk_repository(git_revwalk *walk)
+{
+	assert(walk);
+	return walk->repo;
+}
+
+void git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode)
+{
+	assert(walk);
+
+	if (walk->walking)
+		git_revwalk_reset(walk);
+
+	walk->sorting = sort_mode;
+
+	if (walk->sorting & GIT_SORT_TIME) {
+		walk->get_next = &revwalk_next_timesort;
+		walk->enqueue = &revwalk_enqueue_timesort;
+	} else {
+		walk->get_next = &revwalk_next_unsorted;
+		walk->enqueue = &revwalk_enqueue_unsorted;
+	}
+}
+
+int git_revwalk_next(git_oid *oid, git_revwalk *walk)
+{
+	int error;
+	commit_object *next;
+
+	assert(walk && oid);
+
+	if (!walk->walking) {
+		if ((error = prepare_walk(walk)) < GIT_SUCCESS)
+			return error;
+	}
+
+	error = walk->get_next(&next, walk);
+	if (error < GIT_SUCCESS) {
+		if (error == GIT_EREVWALKOVER)
+			git_revwalk_reset(walk);
+		return error;
+	}
+
+	git_oid_cpy(oid, &next->oid);
+	return GIT_SUCCESS;
+}
+
+void git_revwalk_reset(git_revwalk *walk)
+{
+	const void *_unused;
+	commit_object *commit;
+
+	assert(walk);
+
+	GIT_HASHTABLE_FOREACH(walk->commits, _unused, commit,
+		commit->seen = 0;
+		commit->in_degree = 0;
+		commit->topo_delay = 0;
+	);
+
+	git_pqueue_clear(&walk->iterator_time);
+	commit_list_free(&walk->iterator_topo);
+	commit_list_free(&walk->iterator_rand);
+	commit_list_free(&walk->iterator_reverse);
+	walk->walking = 0;
+}
+
diff --git a/libgit2/src/signature.c b/libgit2/src/signature.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/signature.c
@@ -0,0 +1,199 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "signature.h"
+#include "repository.h"
+#include "git2/common.h"
+
+void git_signature_free(git_signature *sig)
+{
+	if (sig == NULL)
+		return;
+
+	free(sig->name);
+	free(sig->email);
+	free(sig);
+}
+
+git_signature *git_signature_new(const char *name, const char *email, time_t time, int offset)
+{
+	git_signature *p = NULL;
+
+	if ((p = git__malloc(sizeof(git_signature))) == NULL)
+		goto cleanup;
+
+	p->name = git__strdup(name);
+	if (p->name == NULL)
+		goto cleanup;
+
+	p->email = git__strdup(email);
+	if (p->email == NULL)
+		goto cleanup;
+
+	p->when.time = time;
+	p->when.offset = offset;
+
+	if (p->name == NULL || p->email == NULL)
+		goto cleanup;
+
+	return p;
+
+cleanup:
+	git_signature_free(p);
+	return NULL;
+}
+
+git_signature *git_signature_dup(const git_signature *sig)
+{
+	return git_signature_new(sig->name, sig->email, sig->when.time, sig->when.offset);
+}
+
+
+static int parse_timezone_offset(const char *buffer, int *offset_out)
+{
+	int offset, dec_offset;
+	int mins, hours;
+
+	const char* offset_start;
+	char* offset_end;
+
+	offset_start = buffer + 1;
+
+	if (*offset_start == '\n') {
+		*offset_out = 0;
+		return GIT_SUCCESS;
+	}
+
+	if (offset_start[0] != '-' && offset_start[0] != '+')
+		return GIT_EOBJCORRUPTED;
+
+	dec_offset = strtol(offset_start + 1, &offset_end, 10);
+
+	if (offset_end - offset_start != 5)
+		return GIT_EOBJCORRUPTED;
+
+	hours = dec_offset / 100;
+	mins = dec_offset % 100;
+
+	if (hours > 14)	// see http://www.worldtimezone.com/faq.html 
+		return GIT_EOBJCORRUPTED;
+
+	if (mins > 59)
+		return GIT_EOBJCORRUPTED;
+
+	offset = (hours * 60) + mins;
+
+	if (offset_start[0] == '-')
+		offset *= -1;
+	
+	*offset_out = offset;
+
+	return GIT_SUCCESS;
+}
+
+
+int git_signature__parse(git_signature *sig, char **buffer_out,
+		const char *buffer_end, const char *header)
+{
+	const size_t header_len = strlen(header);
+
+	int name_length, email_length;
+	char *buffer = *buffer_out;
+	char *line_end, *name_end, *email_end;
+	int offset = 0;
+
+	memset(sig, 0x0, sizeof(git_signature));
+
+	line_end = memchr(buffer, '\n', buffer_end - buffer);
+	if (!line_end)
+		return GIT_EOBJCORRUPTED;
+
+	if (buffer + (header_len + 1) > line_end)
+		return GIT_EOBJCORRUPTED;
+
+	if (memcmp(buffer, header, header_len) != 0)
+		return GIT_EOBJCORRUPTED;
+
+	buffer += header_len;
+
+	/* Parse name */
+	if ((name_end = memchr(buffer, '<', buffer_end - buffer)) == NULL)
+		return GIT_EOBJCORRUPTED;
+
+	name_length = name_end - buffer - 1;
+	sig->name = git__malloc(name_length + 1);
+	memcpy(sig->name, buffer, name_length);
+	sig->name[name_length] = 0;
+	buffer = name_end + 1;
+
+	if (buffer >= line_end)
+		return GIT_EOBJCORRUPTED;
+
+	/* Parse email */
+	if ((email_end = memchr(buffer, '>', buffer_end - buffer)) == NULL)
+		return GIT_EOBJCORRUPTED;
+
+	email_length = email_end - buffer;
+	sig->email = git__malloc(email_length + 1);
+	memcpy(sig->email, buffer, email_length);
+	sig->email[email_length] = 0;
+	buffer = email_end + 1;
+
+	if (buffer >= line_end)
+		return GIT_EOBJCORRUPTED;
+
+	sig->when.time = strtol(buffer, &buffer, 10);
+
+	if (sig->when.time == 0)
+		return GIT_EOBJCORRUPTED;
+
+	if (parse_timezone_offset(buffer, &offset) < GIT_SUCCESS)
+		return GIT_EOBJCORRUPTED;
+	
+	sig->when.offset = offset;
+
+	*buffer_out = (line_end + 1);
+	return GIT_SUCCESS;
+}
+
+int git_signature__write(git_odb_source *src, const char *header, const git_signature *sig)
+{
+	char sign;
+	int offset, hours, mins;
+
+	offset = sig->when.offset;
+	sign = (sig->when.offset < 0) ? '-' : '+';
+	
+	if (offset < 0)
+		offset = -offset;
+
+	hours = offset / 60;
+	mins = offset % 60;
+
+	return git__source_printf(src, "%s %s <%s> %u %c%02d%02d\n", header, sig->name, sig->email, (unsigned)sig->when.time, sign, hours, mins);
+}
+
+
diff --git a/libgit2/src/signature.h b/libgit2/src/signature.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/signature.h
@@ -0,0 +1,12 @@
+#ifndef INCLUDE_signature_h__
+#define INCLUDE_signature_h__
+
+#include "git2/common.h"
+#include "git2/signature.h"
+#include "repository.h"
+#include <time.h>
+
+int git_signature__parse(git_signature *sig, char **buffer_out, const char *buffer_end, const char *header);
+int git_signature__write(git_odb_source *src, const char *header, const git_signature *sig);
+
+#endif
diff --git a/libgit2/src/t03-data.h b/libgit2/src/t03-data.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/t03-data.h
@@ -0,0 +1,344 @@
+
+typedef struct object_data {
+    char *id;     /* object id (sha1)                          */
+    char *dir;    /* object store (fan-out) directory name     */
+    char *file;   /* object store filename                     */
+} object_data;
+
+static object_data commit = {
+    "3d7f8a6af076c8c3f20071a8935cdbe8228594d1",
+    "test-objects/3d",
+    "test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1",
+};
+
+static unsigned char commit_data[] = {
+    0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66,
+    0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35,
+    0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38,
+    0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32,
+    0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33,
+    0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75,
+    0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55,
+    0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61,
+    0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78,
+    0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+    0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38,
+    0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30,
+    0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d,
+    0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20,
+    0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
+    0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+    0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
+    0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
+    0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
+    0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65,
+    0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f,
+    0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d,
+    0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68,
+    0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f,
+    0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+    0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73,
+    0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f,
+    0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67,
+    0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
+    0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61,
+    0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
+    0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
+    0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+    0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67,
+    0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f,
+    0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79,
+    0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d,
+    0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69,
+    0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d,
+    0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20,
+    0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75,
+    0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61,
+    0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
+    0x3e, 0x0a,
+};
+
+static git_rawobj commit_obj = {
+	commit_data,
+	sizeof(commit_data),
+	GIT_OBJ_COMMIT
+};
+
+static object_data tree = {
+    "dff2da90b254e1beb889d1f1f1288be1803782df",
+    "test-objects/df",
+    "test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df",
+};
+
+static unsigned char tree_data[] = {
+    0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f,
+    0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79,
+    0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b,
+    0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31,
+    0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f,
+    0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86,
+    0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8,
+    0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31,
+    0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77,
+    0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b,
+    0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd,
+    0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30,
+    0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72,
+    0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1,
+    0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a,
+    0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91,
+};
+
+static git_rawobj tree_obj = {
+	tree_data,
+	sizeof(tree_data),
+	GIT_OBJ_TREE
+};
+
+static object_data tag = {
+    "09d373e1dfdc16b129ceec6dd649739911541e05",
+    "test-objects/09",
+    "test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05",
+};
+
+static unsigned char tag_data[] = {
+    0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33,
+    0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66,
+    0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66,
+    0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39,
+    0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32,
+    0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a,
+    0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d,
+    0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20,
+    0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74,
+    0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20,
+    0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
+    0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+    0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
+    0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
+    0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
+    0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
+    0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20,
+    0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+    0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63,
+    0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
+    0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30,
+    0x2e, 0x30, 0x2e, 0x31, 0x0a,
+};
+
+static git_rawobj tag_obj = {
+	tag_data,
+	sizeof(tag_data),
+	GIT_OBJ_TAG
+};
+
+static object_data zero = {
+    "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+    "test-objects/e6",
+    "test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+};
+
+static unsigned char zero_data[] = {
+    0x00  /* dummy data */
+};
+
+static git_rawobj zero_obj = {
+	zero_data,
+	0,
+	GIT_OBJ_BLOB
+};
+
+static object_data one = {
+    "8b137891791fe96927ad78e64b0aad7bded08bdc",
+    "test-objects/8b",
+    "test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc",
+};
+
+static unsigned char one_data[] = {
+    0x0a,
+};
+
+static git_rawobj one_obj = {
+	one_data,
+	sizeof(one_data),
+	GIT_OBJ_BLOB
+};
+
+static object_data two = {
+    "78981922613b2afb6025042ff6bd878ac1994e85",
+    "test-objects/78",
+    "test-objects/78/981922613b2afb6025042ff6bd878ac1994e85",
+};
+
+static unsigned char two_data[] = {
+    0x61, 0x0a,
+};
+
+static git_rawobj two_obj = {
+	two_data,
+	sizeof(two_data),
+	GIT_OBJ_BLOB
+};
+
+static object_data some = {
+    "fd8430bc864cfcd5f10e5590f8a447e01b942bfe",
+    "test-objects/fd",
+    "test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe",
+};
+
+static unsigned char some_data[] = {
+    0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68,
+    0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20,
+    0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20,
+    0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+    0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61,
+    0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74,
+    0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69,
+    0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72,
+    0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a,
+    0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e,
+    0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+    0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66,
+    0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
+    0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+    0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+    0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c,
+    0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+    0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61,
+    0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73,
+    0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+    0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
+    0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+    0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
+    0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a,
+    0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64,
+    0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+    0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65,
+    0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+    0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+    0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e,
+    0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62,
+    0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65,
+    0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20,
+    0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68,
+    0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65,
+    0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c,
+    0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70,
+    0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
+    0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e,
+    0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+    0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20,
+    0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+    0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
+    0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69,
+    0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62,
+    0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+    0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74,
+    0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67,
+    0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a,
+    0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20,
+    0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
+    0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65,
+    0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61,
+    0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69,
+    0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e,
+    0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69,
+    0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a,
+    0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20,
+    0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+    0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20,
+    0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
+    0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65,
+    0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+    0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+    0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
+    0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
+    0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20,
+    0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79,
+    0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65,
+    0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
+    0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20,
+    0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c,
+    0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f,
+    0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d,
+    0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+    0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+    0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c,
+    0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73,
+    0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
+    0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e,
+    0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
+    0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20,
+    0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62,
+    0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65,
+    0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
+    0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20,
+    0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
+    0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73,
+    0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64,
+    0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+    0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61,
+    0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c,
+    0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65,
+    0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74,
+    0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48,
+    0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20,
+    0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59,
+    0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
+    0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74,
+    0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69,
+    0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61,
+    0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20,
+    0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41,
+    0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54,
+    0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54,
+    0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52,
+    0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49,
+    0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55,
+    0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20,
+    0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+    0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47,
+    0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50,
+    0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69,
+    0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f,
+    0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64,
+    0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a,
+    0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f,
+    0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
+    0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65,
+    0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
+    0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66,
+    0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
+    0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+    0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+    0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
+    0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67,
+    0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+    0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
+    0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20,
+    0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65,
+    0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47,
+    0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f,
+    0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65,
+    0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74,
+    0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
+    0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+    0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
+    0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20,
+    0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e,
+    0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c,
+    0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46,
+    0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a,
+    0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c,
+    0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31,
+    0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20,
+    0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f,
+    0x0a,
+};
+
+static git_rawobj some_obj = {
+	some_data,
+	sizeof(some_data),
+	GIT_OBJ_BLOB
+};
diff --git a/libgit2/src/tag.c b/libgit2/src/tag.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/tag.c
@@ -0,0 +1,232 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "commit.h"
+#include "tag.h"
+#include "signature.h"
+#include "git2/object.h"
+#include "git2/repository.h"
+#include "git2/signature.h"
+
+void git_tag__free(git_tag *tag)
+{
+	git_signature_free(tag->tagger);
+	free(tag->message);
+	free(tag->tag_name);
+	free(tag);
+}
+
+const git_oid *git_tag_id(git_tag *c)
+{
+	return git_object_id((git_object *)c);
+}
+
+int git_tag_target(git_object **target, git_tag *t)
+{
+	assert(t);
+	return git_object_lookup(target, t->object.repo, &t->target, t->type);
+}
+
+const git_oid *git_tag_target_oid(git_tag *t)
+{
+	assert(t);
+	return &t->target;
+}
+
+int git_tag_set_target(git_tag *tag, git_object *target)
+{
+	const git_oid *oid;
+
+	assert(tag && target);
+
+	if ((oid = git_object_id(target)) == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	tag->object.modified = 1;
+	git_oid_cpy(&tag->target, oid);
+	tag->type = git_object_type(target);
+	return GIT_SUCCESS;
+}
+
+git_otype git_tag_type(git_tag *t)
+{
+	assert(t);
+	return t->type;
+}
+
+const char *git_tag_name(git_tag *t)
+{
+	assert(t);
+	return t->tag_name;
+}
+
+void git_tag_set_name(git_tag *tag, const char *name)
+{
+	assert(tag && name);
+
+	tag->object.modified = 1;
+
+	if (tag->tag_name)
+		free(tag->tag_name);
+
+	tag->tag_name = git__strdup(name);
+}
+
+const git_signature *git_tag_tagger(git_tag *t)
+{
+	return t->tagger;
+}
+
+void git_tag_set_tagger(git_tag *tag, const git_signature *tagger_sig)
+{
+	assert(tag && tagger_sig);
+	tag->object.modified = 1;
+
+	git_signature_free(tag->tagger);
+	tag->tagger = git_signature_dup(tagger_sig);
+}
+
+const char *git_tag_message(git_tag *t)
+{
+	assert(t);
+	return t->message;
+}
+
+void git_tag_set_message(git_tag *tag, const char *message)
+{
+	assert(tag && message);
+
+	tag->object.modified = 1;
+
+	if (tag->message)
+		free(tag->message);
+
+	tag->message = git__strdup(message);
+}
+
+static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end)
+{
+	static const char *tag_types[] = {
+		NULL, "commit\n", "tree\n", "blob\n", "tag\n"
+	};
+
+	unsigned int i, text_len;
+	char *search;
+	int error;
+
+	if ((error = git__parse_oid(&tag->target, &buffer, buffer_end, "object ")) < 0)
+		return error;
+
+	if (buffer + 5 >= buffer_end)
+		return GIT_EOBJCORRUPTED;
+
+	if (memcmp(buffer, "type ", 5) != 0)
+		return GIT_EOBJCORRUPTED;
+	buffer += 5;
+
+	tag->type = GIT_OBJ_BAD;
+
+	for (i = 1; i < ARRAY_SIZE(tag_types); ++i) {
+		size_t type_length = strlen(tag_types[i]);
+
+		if (buffer + type_length >= buffer_end)
+			return GIT_EOBJCORRUPTED;
+
+		if (memcmp(buffer, tag_types[i], type_length) == 0) {
+			tag->type = i;
+			buffer += type_length;
+			break;
+		}
+	}
+
+	if (tag->type == GIT_OBJ_BAD)
+		return GIT_EOBJCORRUPTED;
+
+	if (buffer + 4 >= buffer_end)
+		return GIT_EOBJCORRUPTED;
+
+	if (memcmp(buffer, "tag ", 4) != 0)
+		return GIT_EOBJCORRUPTED;
+	buffer += 4;
+
+	search = memchr(buffer, '\n', buffer_end - buffer);
+	if (search == NULL)
+		return GIT_EOBJCORRUPTED;
+
+	text_len = search - buffer;
+
+	if (tag->tag_name != NULL)
+		free(tag->tag_name);
+
+	tag->tag_name = git__malloc(text_len + 1);
+	memcpy(tag->tag_name, buffer, text_len);
+	tag->tag_name[text_len] = '\0';
+
+	buffer = search + 1;
+
+	if (tag->tagger != NULL)
+		git_signature_free(tag->tagger);
+
+	tag->tagger = git__malloc(sizeof(git_signature));
+
+	if ((error = git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ")) != 0)
+		return error;
+
+	text_len = buffer_end - ++buffer;
+
+	if (tag->message != NULL)
+		free(tag->message);
+
+	tag->message = git__malloc(text_len + 1);
+	memcpy(tag->message, buffer, text_len);
+	tag->message[text_len] = '\0';
+
+	return GIT_SUCCESS;
+}
+
+int git_tag__writeback(git_tag *tag, git_odb_source *src)
+{
+	if (tag->tag_name == NULL || tag->tagger == NULL)
+		return GIT_EMISSINGOBJDATA;
+
+	git__write_oid(src, "object", &tag->target);
+	git__source_printf(src, "type %s\n", git_object_type2string(tag->type));
+	git__source_printf(src, "tag %s\n", tag->tag_name);
+	git_signature__write(src, "tagger", tag->tagger);
+
+	if (tag->message != NULL)
+		git__source_printf(src, "\n%s", tag->message);
+
+	return GIT_SUCCESS;
+}
+
+
+int git_tag__parse(git_tag *tag)
+{
+	assert(tag && tag->object.source.open);
+	return parse_tag_buffer(tag, tag->object.source.raw.data, (char *)tag->object.source.raw.data + tag->object.source.raw.len);
+}
+
diff --git a/libgit2/src/tag.h b/libgit2/src/tag.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/tag.h
@@ -0,0 +1,22 @@
+#ifndef INCLUDE_tag_h__
+#define INCLUDE_tag_h__
+
+#include "git2/tag.h"
+#include "repository.h"
+
+struct git_tag {
+	git_object object;
+
+	git_oid target;
+	git_otype type;
+
+	char *tag_name;
+	git_signature *tagger;
+	char *message;
+};
+
+void git_tag__free(git_tag *tag);
+int git_tag__parse(git_tag *tag);
+int git_tag__writeback(git_tag *tag, git_odb_source *src);
+
+#endif
diff --git a/libgit2/src/thread-utils.c b/libgit2/src/thread-utils.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/thread-utils.c
@@ -0,0 +1,49 @@
+#include "common.h"
+#include "thread-utils.h"
+
+#ifdef _WIN32
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+#elif defined(hpux) || defined(__hpux) || defined(_hpux)
+#  include <sys/pstat.h>
+#endif
+
+/*
+ * By doing this in two steps we can at least get
+ * the function to be somewhat coherent, even
+ * with this disgusting nest of #ifdefs.
+ */
+#ifndef _SC_NPROCESSORS_ONLN
+#  ifdef _SC_NPROC_ONLN
+#    define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+#  elif defined _SC_CRAY_NCPU
+#    define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU
+#  endif
+#endif
+
+int git_online_cpus(void)
+{
+#ifdef _SC_NPROCESSORS_ONLN
+	long ncpus;
+#endif
+
+#ifdef _WIN32
+	SYSTEM_INFO info;
+	GetSystemInfo(&info);
+
+	if ((int)info.dwNumberOfProcessors > 0)
+		return (int)info.dwNumberOfProcessors;
+#elif defined(hpux) || defined(__hpux) || defined(_hpux)
+	struct pst_dynamic psd;
+
+	if (!pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0))
+		return (int)psd.psd_proc_cnt;
+#endif
+
+#ifdef _SC_NPROCESSORS_ONLN
+	if ((ncpus = (long)sysconf(_SC_NPROCESSORS_ONLN)) > 0)
+		return (int)ncpus;
+#endif
+
+	return 1;
+}
diff --git a/libgit2/src/thread-utils.h b/libgit2/src/thread-utils.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/thread-utils.h
@@ -0,0 +1,28 @@
+#ifndef INCLUDE_thread_utils_h__
+#define INCLUDE_thread_utils_h__
+
+
+#define git_thread pthread_t
+#define git_thread_create(thread, attr, start_routine, arg) pthread_create(thread, attr, start_routine, arg)
+#define git_thread_kill(thread) pthread_cancel(thread)
+#define git_thread_exit(status)	pthread_exit(status)
+#define git_thread_join(id, status) pthread_join(id, status)
+
+/* Pthreads Mutex */
+#define git_mutex pthread_mutex_t
+#define git_mutex_init(a)   pthread_mutex_init(a, NULL)
+#define git_mutex_lock(a)   pthread_mutex_lock(a)
+#define git_mutex_unlock(a) pthread_mutex_unlock(a)
+#define git_mutex_free(a)   pthread_mutex_destroy(a)
+
+/* Pthreads condition vars */
+#define git_cond pthread_cond_t
+#define git_cond_init(c, a)	pthread_cond_init(c, a)
+#define git_cond_free(c)		pthread_cond_destroy(c)
+#define git_cond_wait(c, l)	pthread_cond_wait(c, l)
+#define git_cond_signal(c)		pthread_cond_signal(c)
+#define git_cond_broadcast(c)	pthread_cond_broadcast(c)
+
+extern int git_online_cpus(void);
+
+#endif /* INCLUDE_thread_utils_h__ */
diff --git a/libgit2/src/tree.c b/libgit2/src/tree.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/tree.c
@@ -0,0 +1,351 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "commit.h"
+#include "tree.h"
+#include "git2/repository.h"
+#include "git2/object.h"
+
+#define DEFAULT_TREE_SIZE 16
+#define MAX_FILEMODE 0777777
+#define MAX_FILEMODE_BYTES 6
+
+int entry_search_cmp(const void *key, const void *array_member)
+{
+	const char *filename = (const char *)key;
+	const git_tree_entry *entry = *(const git_tree_entry **)(array_member);
+
+	return strcmp(filename, entry->filename);
+}
+
+static int valid_attributes(const int attributes) {
+	return attributes >= 0 && attributes <= MAX_FILEMODE; 
+}
+
+int entry_sort_cmp(const void *a, const void *b)
+{
+	const git_tree_entry *entry_a = *(const git_tree_entry **)(a);
+	const git_tree_entry *entry_b = *(const git_tree_entry **)(b);
+
+	return gitfo_cmp_path(entry_a->filename, strlen(entry_a->filename),
+                                  entry_a->attr & 040000,
+                                  entry_b->filename, strlen(entry_b->filename),
+                                  entry_b->attr & 040000);
+}
+
+void git_tree_clear_entries(git_tree *tree)
+{
+	unsigned int i;
+
+	if (tree == NULL)
+		return;
+
+	for (i = 0; i < tree->entries.length; ++i) {
+		git_tree_entry *e;
+		e = git_vector_get(&tree->entries, i);
+
+		free(e->filename);
+		free(e);
+	}
+
+	git_vector_clear(&tree->entries);
+	tree->object.modified = 1;
+}
+
+
+git_tree *git_tree__new(void)
+{
+	git_tree *tree;
+
+	tree = git__malloc(sizeof(struct git_tree));
+	if (tree == NULL)
+		return NULL;
+
+	memset(tree, 0x0, sizeof(struct git_tree));
+
+	if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < GIT_SUCCESS) {
+		free(tree);
+		return NULL;
+	}
+
+	return tree;
+}
+
+void git_tree__free(git_tree *tree)
+{
+	git_tree_clear_entries(tree);
+	git_vector_free(&tree->entries);
+	free(tree);
+}
+
+const git_oid *git_tree_id(git_tree *c)
+{
+	return git_object_id((git_object *)c);
+}
+
+int git_tree_entry_set_attributes(git_tree_entry *entry, unsigned int attr)
+{
+	assert(entry && entry->owner);
+	
+	if (!valid_attributes(attr)) {
+		return GIT_ERROR;
+	}
+
+	entry->attr = attr;
+	entry->owner->object.modified = 1;
+	return GIT_SUCCESS;
+}
+
+void git_tree_entry_set_name(git_tree_entry *entry, const char *name)
+{
+	assert(entry && entry->owner);
+
+	free(entry->filename);
+	entry->filename = git__strdup(name);
+	git_vector_sort(&entry->owner->entries);
+	entry->owner->object.modified = 1;
+}
+
+void git_tree_entry_set_id(git_tree_entry *entry, const git_oid *oid)
+{
+	assert(entry && entry->owner);
+
+	git_oid_cpy(&entry->oid, oid);
+	entry->owner->object.modified = 1;
+}
+
+unsigned int git_tree_entry_attributes(git_tree_entry *entry)
+{
+	return entry->attr;
+}
+
+const char *git_tree_entry_name(git_tree_entry *entry)
+{
+	assert(entry);
+	return entry->filename;
+}
+
+const git_oid *git_tree_entry_id(git_tree_entry *entry)
+{
+	assert(entry);
+	return &entry->oid;
+}
+
+int git_tree_entry_2object(git_object **object_out, git_tree_entry *entry)
+{
+	assert(entry && object_out);
+	return git_object_lookup(object_out, entry->owner->object.repo, &entry->oid, GIT_OBJ_ANY);
+}
+
+static void sort_entries(git_tree *tree)
+{
+	git_vector_sort(&tree->entries);
+}
+
+git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
+{
+	int idx;
+
+	assert(tree && filename);
+
+	sort_entries(tree);
+
+	idx = git_vector_bsearch2(&tree->entries, entry_search_cmp, filename);
+	if (idx == GIT_ENOTFOUND)
+		return NULL;
+
+	return git_vector_get(&tree->entries, idx);
+}
+
+git_tree_entry *git_tree_entry_byindex(git_tree *tree, int idx)
+{
+	assert(tree);
+
+	sort_entries(tree);
+
+	return git_vector_get(&tree->entries, (unsigned int)idx);
+}
+
+size_t git_tree_entrycount(git_tree *tree)
+{
+	assert(tree);
+	return tree->entries.length;
+}
+
+int git_tree_add_entry(git_tree_entry **entry_out, git_tree *tree, const git_oid *id, const char *filename, int attributes)
+{
+	git_tree_entry *entry;
+
+	assert(tree && id && filename);
+	if (!valid_attributes(attributes)) {
+	  return GIT_ERROR;
+	}
+
+	if ((entry = git__malloc(sizeof(git_tree_entry))) == NULL)
+		return GIT_ENOMEM;
+
+	memset(entry, 0x0, sizeof(git_tree_entry));
+
+	entry->filename = git__strdup(filename);
+	git_oid_cpy(&entry->oid, id);
+	entry->attr = attributes;
+	entry->owner = tree;
+
+	if (git_vector_insert(&tree->entries, entry) < 0)
+		return GIT_ENOMEM;
+
+	if (entry_out != NULL)
+		*entry_out = entry;
+
+	tree->object.modified = 1;
+	return GIT_SUCCESS;
+}
+
+int git_tree_remove_entry_byindex(git_tree *tree, int idx)
+{
+	git_tree_entry *remove_ptr;
+
+	assert(tree);
+
+	sort_entries(tree);
+
+	remove_ptr = git_vector_get(&tree->entries, (unsigned int)idx);
+	if (remove_ptr == NULL)
+		return GIT_ENOTFOUND;
+
+	free(remove_ptr->filename);
+	free(remove_ptr);
+
+	tree->object.modified = 1;
+
+	return git_vector_remove(&tree->entries, (unsigned int)idx);
+}
+
+int git_tree_remove_entry_byname(git_tree *tree, const char *filename)
+{
+	int idx;
+
+	assert(tree && filename);
+
+	sort_entries(tree);
+
+	idx = git_vector_bsearch2(&tree->entries, entry_search_cmp, filename);
+	if (idx == GIT_ENOTFOUND)
+		return GIT_ENOTFOUND;
+
+	return git_tree_remove_entry_byindex(tree, idx);
+}
+
+int git_tree__writeback(git_tree *tree, git_odb_source *src)
+{
+	size_t i;
+	char filemode[MAX_FILEMODE_BYTES + 1 + 1];
+
+	assert(tree && src);
+
+	if (tree->entries.length == 0)
+		return GIT_EMISSINGOBJDATA;
+
+	sort_entries(tree);
+
+	for (i = 0; i < tree->entries.length; ++i) {
+		git_tree_entry *entry;
+
+		entry = git_vector_get(&tree->entries, i);
+	
+		snprintf(filemode, sizeof(filemode), "%o ", entry->attr);
+		  
+		git__source_write(src, filemode, strlen(filemode));
+		git__source_write(src, entry->filename, strlen(entry->filename) + 1);
+		git__source_write(src, entry->oid.id, GIT_OID_RAWSZ);
+	} 
+
+	return GIT_SUCCESS;
+}
+
+
+static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
+{
+	static const size_t avg_entry_size = 40;
+	unsigned int expected_size;
+	int error = GIT_SUCCESS;
+
+	expected_size = (tree->object.source.raw.len / avg_entry_size) + 1;
+
+	git_tree_clear_entries(tree);
+
+	while (buffer < buffer_end) {
+		git_tree_entry *entry;
+
+		entry = git__malloc(sizeof(git_tree_entry));
+		if (entry == NULL) {
+			error = GIT_ENOMEM;
+			break;
+		}
+
+		if (git_vector_insert(&tree->entries, entry) < GIT_SUCCESS)
+			return GIT_ENOMEM;
+
+		entry->owner = tree;
+		entry->attr = strtol(buffer, &buffer, 8);
+
+		if (*buffer++ != ' ') {
+			error = GIT_EOBJCORRUPTED;
+			break;
+		}
+
+		if (memchr(buffer, 0, buffer_end - buffer) == NULL) {
+			error = GIT_EOBJCORRUPTED;
+			break;
+		}
+
+		entry->filename = git__strdup(buffer);
+
+		while (buffer < buffer_end && *buffer != 0)
+			buffer++;
+
+		buffer++;
+
+		git_oid_mkraw(&entry->oid, (const unsigned char *)buffer);
+		buffer += GIT_OID_RAWSZ;
+	}
+
+	return error;
+}
+
+int git_tree__parse(git_tree *tree)
+{
+	char *buffer, *buffer_end;
+
+	assert(tree && tree->object.source.open);
+	assert(!tree->object.in_memory);
+
+	buffer = tree->object.source.raw.data;
+	buffer_end = buffer + tree->object.source.raw.len;
+
+	return tree_parse_buffer(tree, buffer, buffer_end);
+}
+
diff --git a/libgit2/src/tree.h b/libgit2/src/tree.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/tree.h
@@ -0,0 +1,26 @@
+#ifndef INCLUDE_tree_h__
+#define INCLUDE_tree_h__
+
+#include "git2/tree.h"
+#include "repository.h"
+#include "vector.h"
+
+struct git_tree_entry {
+	unsigned int attr;
+	char *filename;
+	git_oid oid;
+
+	git_tree *owner;
+};
+
+struct git_tree {
+	git_object object;
+	git_vector entries;
+};
+
+void git_tree__free(git_tree *tree);
+git_tree *git_tree__new(void);
+int git_tree__parse(git_tree *tree);
+int git_tree__writeback(git_tree *tree, git_odb_source *src);
+
+#endif
diff --git a/libgit2/src/unix/map.c b/libgit2/src/unix/map.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/unix/map.c
@@ -0,0 +1,61 @@
+
+#include "map.h"
+#include <sys/mman.h>
+#include <errno.h>
+
+
+int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
+{
+	int mprot = 0;
+	int mflag = 0;
+
+	assert((out != NULL) && (len > 0));
+
+	if ((out == NULL) || (len == 0)) {
+		errno = EINVAL;
+		return GIT_ERROR;
+	}
+
+	out->data = NULL;
+	out->len = 0;
+
+	if (prot & GIT_PROT_WRITE)
+		mprot = PROT_WRITE;
+	else if (prot & GIT_PROT_READ)
+		mprot = PROT_READ;
+	else {
+		errno = EINVAL;
+		return GIT_ERROR;
+	}
+
+	if ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)
+		mflag = MAP_SHARED;
+	else if ((flags & GIT_MAP_TYPE) == GIT_MAP_PRIVATE)
+		mflag = MAP_PRIVATE;
+
+	if (flags & GIT_MAP_FIXED) {
+		errno = EINVAL;
+		return GIT_ERROR;
+	}
+
+	out->data = mmap(NULL, len, mprot, mflag, fd, offset);
+	if (!out->data || out->data == MAP_FAILED)
+		return GIT_EOSERR;
+	out->len = len;
+
+	return GIT_SUCCESS;
+}
+
+int git__munmap(git_map *map)
+{
+	assert(map != NULL);
+
+	if (!map)
+		return GIT_ERROR;
+
+	munmap(map->data, map->len);
+
+	return GIT_SUCCESS;
+}
+
+
diff --git a/libgit2/src/util.c b/libgit2/src/util.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/util.c
@@ -0,0 +1,406 @@
+#define GIT__NO_HIDE_MALLOC
+#include "common.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+void git_strarray_free(git_strarray *array)
+{
+	size_t i;
+	for (i = 0; i < array->count; ++i)
+		free(array->strings[i]);
+
+	free(array->strings);
+}
+
+int git__fmt(char *buf, size_t buf_sz, const char *fmt, ...)
+{
+	va_list va;
+	int r;
+
+	va_start(va, fmt);
+	r = vsnprintf(buf, buf_sz, fmt, va);
+	va_end(va);
+	if (r < 0 || ((size_t) r) >= buf_sz)
+		return GIT_ERROR;
+	return r;
+}
+
+int git__prefixcmp(const char *str, const char *prefix)
+{
+	for (;;) {
+		char p = *(prefix++), s;
+		if (!p)
+			return 0;
+		if ((s = *(str++)) != p)
+			return s - p;
+	}
+}
+
+int git__suffixcmp(const char *str, const char *suffix)
+{
+	size_t a = strlen(str);
+	size_t b = strlen(suffix);
+	if (a < b)
+		return -1;
+	return strcmp(str + (a - b), suffix);
+}
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git__basename_r(char *buffer, size_t bufflen, const char *path)
+{
+	const char *endp, *startp;
+	int len, result;
+
+	/* Empty or NULL string gets treated as "." */
+	if (path == NULL || *path == '\0') {
+		startp  = ".";
+		len     = 1;
+		goto Exit;
+	}
+
+	/* Strip trailing slashes */
+	endp = path + strlen(path) - 1;
+	while (endp > path && *endp == '/')
+		endp--;
+
+	/* All slashes becomes "/" */
+	if (endp == path && *endp == '/') {
+		startp = "/";
+		len    = 1;
+		goto Exit;
+	}
+
+	/* Find the start of the base */
+	startp = endp;
+	while (startp > path && *(startp - 1) != '/')
+		startp--;
+
+	len = endp - startp +1;
+
+Exit:
+	result = len;
+	if (buffer == NULL) {
+		return result;
+	}
+	if (len > (int)bufflen-1) {
+		len    = (int)bufflen-1;
+		result = GIT_ENOMEM;
+	}
+
+	if (len >= 0) {
+		memmove(buffer, startp, len);
+		buffer[len] = 0;
+	}
+	return result;
+}
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git__dirname_r(char *buffer, size_t bufflen, const char *path)
+{
+    const char *endp;
+    int result, len;
+
+    /* Empty or NULL string gets treated as "." */
+    if (path == NULL || *path == '\0') {
+        path = ".";
+        len  = 1;
+        goto Exit;
+    }
+
+    /* Strip trailing slashes */
+    endp = path + strlen(path) - 1;
+    while (endp > path && *endp == '/')
+        endp--;
+
+    /* Find the start of the dir */
+    while (endp > path && *endp != '/')
+        endp--;
+
+    /* Either the dir is "/" or there are no slashes */
+    if (endp == path) {
+        path = (*endp == '/') ? "/" : ".";
+        len  = 1;
+        goto Exit;
+    }
+
+    do {
+        endp--;
+    } while (endp > path && *endp == '/');
+
+    len = endp - path +1;
+
+Exit:
+    result = len;
+    if (len+1 > GIT_PATH_MAX) {
+        return GIT_ENOMEM;
+    }
+    if (buffer == NULL)
+        return result;
+
+    if (len > (int)bufflen-1) {
+        len    = (int)bufflen-1;
+        result = GIT_ENOMEM;
+    }
+
+    if (len >= 0) {
+        memmove(buffer, path, len);
+        buffer[len] = 0;
+    }
+    return result;
+}
+
+
+char *git__dirname(const char *path)
+{
+    char *dname = NULL;
+    int len;
+
+	len = (path ? strlen(path) : 0) + 2;
+	dname = (char *)git__malloc(len);
+	if (dname == NULL)
+		return NULL;
+
+    if (git__dirname_r(dname, len, path) < GIT_SUCCESS) {
+		free(dname);
+		return NULL;
+	}
+
+    return dname;
+}
+
+char *git__basename(const char *path)
+{
+    char *bname = NULL;
+    int len;
+
+	len = (path ? strlen(path) : 0) + 2;
+	bname = (char *)git__malloc(len);
+	if (bname == NULL)
+		return NULL;
+
+    if (git__basename_r(bname, len, path) < GIT_SUCCESS) {
+		free(bname);
+		return NULL;
+	}
+
+    return bname;
+}
+
+
+const char *git__topdir(const char *path)
+{
+	size_t len;
+	int i;
+
+	assert(path);
+	len = strlen(path);
+
+	if (!len || path[len - 1] != '/')
+		return NULL;
+
+	for (i = len - 2; i >= 0; --i)
+		if (path[i] == '/')
+			break;
+
+	return &path[i + 1];
+}
+
+void git__joinpath_n(char *buffer_out, int count, ...)
+{
+	va_list ap;
+	int i;
+	char *buffer_start = buffer_out;
+
+	va_start(ap, count);
+	for (i = 0; i < count; ++i) {
+		const char *path;
+		int len;
+
+		path = va_arg(ap, const char *);
+		if (i > 0 && *path == '/' && buffer_out > buffer_start && buffer_out[-1] == '/')
+			path++;
+
+		if (!*path)
+			continue;
+
+		len = strlen(path);
+		memmove(buffer_out, path, len);
+		buffer_out = buffer_out + len;
+
+		if (i < count - 1 && buffer_out[-1] != '/')
+			*buffer_out++ = '/';
+	}
+	va_end(ap);
+
+	*buffer_out = '\0';
+}
+
+static char *strtok_raw(char *output, char *src, char *delimit, int keep)
+{
+	while (*src && strchr(delimit, *src) == NULL)
+		*output++ = *src++;
+
+	*output = 0;
+
+	if (keep)
+		return src;
+	else
+		return *src ? src+1 : src;
+}
+
+char *git__strtok(char *output, char *src, char *delimit)
+{
+	return strtok_raw(output, src, delimit, 0);
+}
+
+char *git__strtok_keep(char *output, char *src, char *delimit)
+{
+	return strtok_raw(output, src, delimit, 1);
+}
+
+void git__hexdump(const char *buffer, size_t len)
+{
+	static const size_t LINE_WIDTH = 16;
+
+	size_t line_count, last_line, i, j;
+	const char *line;
+
+	line_count = (len / LINE_WIDTH);
+	last_line = (len % LINE_WIDTH);
+
+	for (i = 0; i < line_count; ++i) {
+		line = buffer + (i * LINE_WIDTH);
+		for (j = 0; j < LINE_WIDTH; ++j, ++line)
+			printf("%02X ", (unsigned char)*line & 0xFF);
+
+		printf("| ");
+
+		line = buffer + (i * LINE_WIDTH);
+		for (j = 0; j < LINE_WIDTH; ++j, ++line)
+			printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
+
+		printf("\n");
+	}
+
+	if (last_line > 0) {
+
+		line = buffer + (line_count * LINE_WIDTH);
+		for (j = 0; j < last_line; ++j, ++line)
+			printf("%02X ", (unsigned char)*line & 0xFF);
+
+		for (j = 0; j < (LINE_WIDTH - last_line); ++j)
+			printf("   ");
+
+		printf("| ");
+
+		line = buffer + (line_count * LINE_WIDTH);
+		for (j = 0; j < last_line; ++j, ++line)
+			printf("%c", (*line >= 32 && *line <= 126) ? *line : '.');
+
+		printf("\n");
+	}
+
+	printf("\n");
+}
+
+#ifdef GIT_LEGACY_HASH
+uint32_t git__hash(const void *key, int len, unsigned int seed)
+{
+	const uint32_t m = 0x5bd1e995;
+	const int r = 24;
+	uint32_t h = seed ^ len;
+
+	const unsigned char *data = (const unsigned char *)key;
+
+	while(len >= 4) {
+		uint32_t k = *(uint32_t *)data;
+
+		k *= m; 
+		k ^= k >> r; 
+		k *= m; 
+		
+		h *= m; 
+		h ^= k;
+
+		data += 4;
+		len -= 4;
+	}
+	
+	switch(len) {
+	case 3: h ^= data[2] << 16;
+	case 2: h ^= data[1] << 8;
+	case 1: h ^= data[0];
+	        h *= m;
+	};
+
+	h ^= h >> 13;
+	h *= m;
+	h ^= h >> 15;
+
+	return h;
+} 
+#else
+/*
+	Cross-platform version of Murmurhash3
+	http://code.google.com/p/smhasher/wiki/MurmurHash3
+	by Austin Appleby (aappleby@gmail.com)
+
+	This code is on the public domain.
+*/
+uint32_t git__hash(const void *key, int len, uint32_t seed)
+{
+
+#define MURMUR_BLOCK() {\
+    k1 *= c1; \
+    k1  = git__rotl(k1,11);\
+    k1 *= c2;\
+    h1 ^= k1;\
+    h1 = h1*3 + 0x52dce729;\
+    c1 = c1*5 + 0x7b7d159c;\
+    c2 = c2*5 + 0x6bce6396;\
+}
+
+	const uint8_t *data = (const uint8_t*)key;
+	const int nblocks = len / 4;
+
+	const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
+	const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
+
+	uint32_t h1 = 0x971e137b ^ seed;
+	uint32_t k1;
+
+	uint32_t c1 = 0x95543787;
+	uint32_t c2 = 0x2ad7eb25;
+
+	int i;
+
+	for (i = -nblocks; i; i++) {
+		k1 = blocks[i];
+		MURMUR_BLOCK();
+	}
+
+	k1 = 0;
+
+	switch(len & 3) {
+	case 3: k1 ^= tail[2] << 16;
+	case 2: k1 ^= tail[1] << 8;
+	case 1: k1 ^= tail[0];
+			MURMUR_BLOCK();
+	}
+
+	h1 ^= len;
+	h1 ^= h1 >> 16;
+	h1 *= 0x85ebca6b;
+	h1 ^= h1 >> 13;
+	h1 *= 0xc2b2ae35;
+	h1 ^= h1 >> 16;
+
+	return h1;
+} 
+#endif
diff --git a/libgit2/src/util.h b/libgit2/src/util.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/util.h
@@ -0,0 +1,119 @@
+#ifndef INCLUDE_util_h__
+#define INCLUDE_util_h__
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define bitsizeof(x)  (CHAR_BIT * sizeof(x))
+#define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
+
+/* 
+ * Don't wrap malloc/calloc.
+ * Use the default versions in glibc, and make
+ * sure that any methods that allocate memory
+ * return a GIT_ENOMEM error when allocation
+ * fails.
+ */
+#define git__malloc malloc
+#define git__calloc calloc
+#define git__strdup strdup
+
+extern int git__fmt(char *, size_t, const char *, ...)
+	GIT_FORMAT_PRINTF(3, 4);
+extern int git__prefixcmp(const char *str, const char *prefix);
+extern int git__suffixcmp(const char *str, const char *suffix);
+
+/*
+ * The dirname() function shall take a pointer to a character string
+ * that contains a pathname, and return a pointer to a string that is a
+ * pathname of the parent directory of that file. Trailing '/' characters
+ * in the path are not counted as part of the path.
+ *
+ * If path does not contain a '/', then dirname() shall return a pointer to
+ * the string ".". If path is a null pointer or points to an empty string,
+ * dirname() shall return a pointer to the string "." .
+ *
+ * The `git__dirname` implementation is thread safe. The returned 
+ * string must be manually free'd.
+ *
+ * The `git__dirname_r` implementation expects a string allocated
+ * by the user with big enough size.
+ */
+extern char *git__dirname(const char *path);
+extern int git__dirname_r(char *buffer, size_t bufflen, const char *path);
+
+/*
+ * This function returns the basename of the file, which is the last
+ * part of its full name given by fname, with the drive letter and
+ * leading directories stripped off. For example, the basename of
+ * c:/foo/bar/file.ext is file.ext, and the basename of a:foo is foo.
+ *
+ * Trailing slashes and backslashes are significant: the basename of
+ * c:/foo/bar/ is an empty string after the rightmost slash.
+ *
+ * The `git__basename` implementation is thread safe. The returned 
+ * string must be manually free'd.
+ *
+ * The `git__basename_r` implementation expects a string allocated
+ * by the user with big enough size.
+ */
+extern char *git__basename(const char *path);
+extern int git__basename_r(char *buffer, size_t bufflen, const char *path);
+
+extern const char *git__topdir(const char *path);
+
+/**
+ * Join two paths together. Takes care of properly fixing the
+ * middle slashes and everything
+ *
+ * The paths are joined together into buffer_out; this is expected
+ * to be an user allocated buffer of `GIT_PATH_MAX` size 
+ */
+extern void git__joinpath_n(char *buffer_out, int npath, ...);
+
+GIT_INLINE(void) git__joinpath(char *buffer_out, const char *path_a, const char *path_b)
+{
+	git__joinpath_n(buffer_out, 2, path_a, path_b);
+}
+
+extern void git__hexdump(const char *buffer, size_t n);
+extern uint32_t git__hash(const void *key, int len, uint32_t seed);
+
+
+/** @return true if p fits into the range of a size_t */
+GIT_INLINE(int) git__is_sizet(git_off_t p)
+{
+	size_t r = (size_t)p;
+	return p == (git_off_t)r;
+}
+
+/* 32-bit cross-platform rotl */
+#ifdef _MSC_VER /* use built-in method in MSVC */
+#	define git__rotl(v, s) (uint32_t)_rotl(v, s)
+#else /* use bitops in GCC; with o2 this gets optimized to a rotl instruction */
+#	define git__rotl(v, s) (uint32_t)(((uint32_t)(v) << (s)) | ((uint32_t)(v) >> (32 - (s))))
+#endif
+
+extern char *git__strtok(char *output, char *src, char *delimit);
+extern char *git__strtok_keep(char *output, char *src, char *delimit);
+
+#define STRLEN(str) (sizeof(str) - 1)
+
+/*
+ * Realloc the buffer pointed at by variable 'x' so that it can hold
+ * at least 'nr' entries; the number of entries currently allocated
+ * is 'alloc', using the standard growing factor alloc_nr() macro.
+ *
+ * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
+ */
+#define alloc_nr(x) (((x)+16)*3/2)
+#define ALLOC_GROW(x, nr, alloc) \
+	do { \
+		if ((nr) > alloc) { \
+			if (alloc_nr(alloc) < (nr)) \
+				alloc = (nr); \
+			else \
+				alloc = alloc_nr(alloc); \
+			x = xrealloc((x), alloc * sizeof(*(x))); \
+		} \
+	} while (0)
+
+#endif /* INCLUDE_util_h__ */
diff --git a/libgit2/src/vector.c b/libgit2/src/vector.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/vector.c
@@ -0,0 +1,175 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "common.h"
+#include "repository.h"
+#include "vector.h"
+
+static const double resize_factor = 1.75;
+static const size_t minimum_size = 8;
+
+static int resize_vector(git_vector *v)
+{
+	v->_alloc_size = ((unsigned int)(v->_alloc_size * resize_factor)) + 1;
+	if (v->_alloc_size < minimum_size)
+		v->_alloc_size = minimum_size;
+
+	v->contents = realloc(v->contents, v->_alloc_size * sizeof(void *));
+	if (v->contents == NULL)
+		return GIT_ENOMEM;
+
+	return GIT_SUCCESS;
+}
+
+
+void git_vector_free(git_vector *v)
+{
+	assert(v);
+	free(v->contents);
+}
+
+int git_vector_init(git_vector *v, unsigned int initial_size, git_vector_cmp cmp)
+{
+	assert(v);
+
+	memset(v, 0x0, sizeof(git_vector));
+
+	if (initial_size == 0)
+		initial_size = minimum_size;
+
+	v->_alloc_size = initial_size;
+	v->_cmp = cmp;
+	
+	v->length = 0;
+	v->sorted = 1;
+
+	v->contents = git__malloc(v->_alloc_size * sizeof(void *));
+	if (v->contents == NULL)
+		return GIT_ENOMEM;
+
+	return GIT_SUCCESS;
+}
+
+int git_vector_insert(git_vector *v, void *element)
+{
+	assert(v);
+
+	if (v->length >= v->_alloc_size) {
+		if (resize_vector(v) < 0)
+			return GIT_ENOMEM;
+	}
+
+	v->contents[v->length++] = element;
+	v->sorted = 0;
+
+	return GIT_SUCCESS;
+}
+
+void git_vector_sort(git_vector *v)
+{
+	assert(v);
+
+	if (v->sorted || v->_cmp == NULL)
+		return;
+
+	qsort(v->contents, v->length, sizeof(void *), v->_cmp);
+	v->sorted = 1;
+}
+
+int git_vector_bsearch2(git_vector *v, git_vector_cmp key_lookup, const void *key)
+{
+	void **find;
+
+	assert(v && key && key_lookup);
+
+	/* need comparison function to sort the vector */
+	if (v->_cmp == NULL)
+		return GIT_ENOTFOUND;
+
+	git_vector_sort(v);
+
+	find = bsearch(key, v->contents, v->length, sizeof(void *), key_lookup);
+	if (find != NULL)
+		return (int)(find - v->contents);
+
+	return GIT_ENOTFOUND;
+}
+
+int git_vector_search2(git_vector *v, git_vector_cmp key_lookup, const void *key)
+{
+	unsigned int i;
+
+	assert(v && key && key_lookup);
+
+	for (i = 0; i < v->length; ++i) {
+		if (key_lookup(key, v->contents[i]) == 0)
+			return i;
+	}
+
+	return GIT_ENOTFOUND;
+}
+
+static int strict_comparison(const void *a, const void *b)
+{
+	return (a == b) ? 0 : -1;
+}
+
+int git_vector_search(git_vector *v, const void *entry)
+{
+	return git_vector_search2(v, v->_cmp ? v->_cmp : strict_comparison, entry);
+}
+
+int git_vector_bsearch(git_vector *v, const void *key)
+{
+	if (v->_cmp == NULL)
+		return GIT_ENOTFOUND;
+
+	return git_vector_bsearch2(v, v->_cmp, key);
+}
+
+int git_vector_remove(git_vector *v, unsigned int idx)
+{
+	unsigned int i;
+
+	assert(v);
+
+	if (idx >= v->length || v->length == 0)
+		return GIT_ENOTFOUND;
+
+	for (i = idx; i < v->length - 1; ++i)
+		v->contents[i] = v->contents[i + 1];
+
+	v->length--;
+	return GIT_SUCCESS;
+}
+
+void git_vector_clear(git_vector *v)
+{
+	assert(v);
+	v->length = 0;
+	v->sorted = 1;
+}
+
+
diff --git a/libgit2/src/vector.h b/libgit2/src/vector.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/vector.h
@@ -0,0 +1,36 @@
+#ifndef INCLUDE_vector_h__
+#define INCLUDE_vector_h__
+
+#include "git2/common.h"
+
+typedef int (*git_vector_cmp)(const void *, const void *);
+
+typedef struct git_vector {
+	unsigned int _alloc_size;
+	git_vector_cmp _cmp;
+	void **contents;
+	unsigned int length;
+	int sorted;
+} git_vector;
+
+int git_vector_init(git_vector *v, unsigned int initial_size, git_vector_cmp cmp);
+void git_vector_free(git_vector *v);
+void git_vector_clear(git_vector *v);
+
+int git_vector_search(git_vector *v, const void *entry);
+int git_vector_search2(git_vector *v, git_vector_cmp cmp, const void *key);
+
+int git_vector_bsearch(git_vector *v, const void *entry);
+int git_vector_bsearch2(git_vector *v, git_vector_cmp cmp, const void *key);
+
+void git_vector_sort(git_vector *v);
+
+GIT_INLINE(void *) git_vector_get(git_vector *v, unsigned int position)
+{
+	return (position < v->length) ? v->contents[position] : NULL;
+}
+
+int git_vector_insert(git_vector *v, void *element);
+int git_vector_remove(git_vector *v, unsigned int idx);
+
+#endif
diff --git a/libgit2/src/win32/dir.c b/libgit2/src/win32/dir.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/win32/dir.c
@@ -0,0 +1,98 @@
+#define GIT__WIN32_NO_WRAP_DIR
+#include "dir.h"
+
+static int init_filter(char *filter, size_t n, const char *dir)
+{
+	size_t len = strlen(dir);
+
+	if (len+3 >= n)
+		return 0;
+
+	strcpy(filter, dir);
+	if (len && dir[len-1] != '/')
+		strcat(filter, "/");
+	strcat(filter, "*");
+
+	return 1;
+}
+
+git__DIR *git__opendir(const char *dir)
+{
+	char filter[4096];
+	git__DIR *new;
+
+	if (!dir || !init_filter(filter, sizeof(filter), dir))
+		return NULL;
+
+	new = git__malloc(sizeof(*new));
+	if (!new)
+		return NULL;
+
+	new->dir = git__malloc(strlen(dir)+1);
+	if (!new->dir) {
+		free(new);
+		return NULL;
+	}
+	strcpy(new->dir, dir);
+
+	new->h = FindFirstFile(filter, &new->f);
+	if (new->h == INVALID_HANDLE_VALUE) {
+		free(new->dir);
+		free(new);
+		return NULL;
+	}
+	new->first = 1;
+
+	return new;
+}
+
+struct git__dirent *git__readdir(git__DIR *d)
+{
+	if (!d || d->h == INVALID_HANDLE_VALUE)
+		return NULL;
+
+	if (d->first)
+		d->first = 0;
+	else {
+		if (!FindNextFile(d->h, &d->f))
+			return NULL;
+	}
+
+	if (strlen(d->f.cFileName) >= sizeof(d->entry.d_name))
+		return NULL;
+
+	d->entry.d_ino = 0;
+	strcpy(d->entry.d_name, d->f.cFileName);
+
+	return &d->entry;
+}
+
+void git__rewinddir(git__DIR *d)
+{
+	char filter[4096];
+
+	if (d) {
+		if (d->h != INVALID_HANDLE_VALUE)
+			FindClose(d->h);
+		d->h = INVALID_HANDLE_VALUE;
+		d->first = 0;
+		if (init_filter(filter, sizeof(filter), d->dir)) {
+			d->h = FindFirstFile(filter, &d->f);
+			if (d->h != INVALID_HANDLE_VALUE)
+				d->first = 1;
+		}
+	}
+}
+
+int git__closedir(git__DIR *d)
+{
+	if (d) {
+		if (d->h != INVALID_HANDLE_VALUE)
+			FindClose(d->h);
+		if (d->dir)
+			free(d->dir);
+		free(d);
+	}
+	return 0;
+}
+
diff --git a/libgit2/src/win32/fileops.c b/libgit2/src/win32/fileops.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/win32/fileops.c
@@ -0,0 +1,41 @@
+#define GIT__WIN32_NO_HIDE_FILEOPS
+#include "fileops.h"
+#include <errno.h>
+
+int git__unlink(const char *path)
+{
+	chmod(path, 0666);
+	return unlink(path);
+}
+
+int git__mkstemp(char *template)
+{
+	char *file = mktemp(template);
+	if (file == NULL)
+		return -1;
+	return open(file, O_RDWR | O_CREAT | O_BINARY, 0600);
+}
+
+int git__fsync(int fd)
+{
+	HANDLE fh = (HANDLE)_get_osfhandle(fd);
+
+	if (fh == INVALID_HANDLE_VALUE) {
+		errno = EBADF;
+		return -1;
+	}
+
+	if (!FlushFileBuffers(fh)) {
+		DWORD code = GetLastError();
+
+		if (code == ERROR_INVALID_HANDLE)
+			errno = EINVAL;
+		else
+			errno = EIO;
+
+		return -1;
+	}
+
+	return 0;
+}
+
diff --git a/libgit2/src/win32/map.c b/libgit2/src/win32/map.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/win32/map.c
@@ -0,0 +1,125 @@
+
+#include "map.h"
+#include <errno.h>
+
+
+static DWORD get_page_size(void)
+{
+	static DWORD page_size;
+	SYSTEM_INFO sys;
+
+	if (!page_size) {
+		GetSystemInfo(&sys);
+		page_size = sys.dwAllocationGranularity;
+	}
+
+	return page_size;
+}
+
+int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
+{
+	HANDLE fh = (HANDLE)_get_osfhandle(fd);
+	DWORD page_size = get_page_size();
+	DWORD fmap_prot = 0;
+	DWORD view_prot = 0;
+	DWORD off_low = 0;
+	DWORD off_hi  = 0;
+	git_off_t page_start;
+	git_off_t page_offset;
+
+	assert((out != NULL) && (len > 0));
+
+	if ((out == NULL) || (len == 0)) {
+		errno = EINVAL;
+		return GIT_ERROR;
+	}
+
+	out->data = NULL;
+	out->len = 0;
+	out->fmh = NULL;
+
+	if (fh == INVALID_HANDLE_VALUE) {
+		errno = EBADF;
+		return GIT_ERROR;
+	}
+
+	if (prot & GIT_PROT_WRITE)
+		fmap_prot |= PAGE_READWRITE;
+	else if (prot & GIT_PROT_READ)
+		fmap_prot |= PAGE_READONLY;
+	else {
+		errno = EINVAL;
+		return GIT_ERROR;
+	}
+
+	if (prot & GIT_PROT_WRITE)
+		view_prot |= FILE_MAP_WRITE;
+	if (prot & GIT_PROT_READ)
+		view_prot |= FILE_MAP_READ;
+
+	if (flags & GIT_MAP_FIXED) {
+		errno = EINVAL;
+		return GIT_ERROR;
+	}
+
+	page_start = (offset / page_size) * page_size;
+	page_offset = offset - page_start;
+
+	if (page_offset != 0) {  /* offset must be multiple of page size */
+		errno = EINVAL;
+		return GIT_ERROR;
+	}
+
+	out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
+	if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
+		/* errno = ? */
+		out->fmh = NULL;
+		return GIT_ERROR;
+	}
+
+	assert(sizeof(git_off_t) == 8);
+	off_low = (DWORD)(page_start);
+	off_hi = (DWORD)(page_start >> 32);
+	out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len);
+	if (!out->data) {
+		/* errno = ? */
+		CloseHandle(out->fmh);
+		out->fmh = NULL;
+		return GIT_ERROR;
+	}
+	out->len = len;
+
+	return GIT_SUCCESS;
+}
+
+int git__munmap(git_map *map)
+{
+	assert(map != NULL);
+
+	if (!map)
+		return GIT_ERROR;
+
+	if (map->data) {
+		if (!UnmapViewOfFile(map->data)) {
+			/* errno = ? */
+			CloseHandle(map->fmh);
+			map->data = NULL;
+			map->fmh = NULL;
+			return GIT_ERROR;
+		}
+		map->data = NULL;
+	}
+
+	if (map->fmh) {
+		if (!CloseHandle(map->fmh)) {
+			/* errno = ? */
+			map->fmh = NULL;
+			return GIT_ERROR;
+		}
+		map->fmh = NULL;
+	}
+
+	return GIT_SUCCESS;
+}
+
+
diff --git a/libgit2/src/win32/pthread.c b/libgit2/src/win32/pthread.c
new file mode 100644
--- /dev/null
+++ b/libgit2/src/win32/pthread.c
@@ -0,0 +1,120 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *  Original code by Ramiro Polla (Public Domain)
+ */
+
+#include "pthread.h"
+
+int pthread_create(pthread_t *GIT_RESTRICT thread,
+                   const pthread_attr_t *GIT_RESTRICT GIT_UNUSED(attr),
+                   void *(*start_routine)(void*), void *GIT_RESTRICT arg)
+{
+	GIT_UNUSED_ARG(attr);
+	*thread = (pthread_t) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
+	return *thread ? GIT_SUCCESS : GIT_EOSERR;
+}
+
+int pthread_cond_signal(pthread_cond_t *cond)
+{
+    WakeConditionVariable(cond);
+    return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t *GIT_RESTRICT cond,
+                      pthread_mutex_t *GIT_RESTRICT mutex)
+{
+    int ret;
+    ret = SleepConditionVariableCS(cond, mutex, INFINITE);
+    return -(!ret);
+}
+
+int pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+    EnterCriticalSection(mutex);
+    return 0;
+}
+
+int pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+    LeaveCriticalSection(mutex);
+    return 0;
+}
+
+int pthread_join(pthread_t thread, void **value_ptr)
+{
+    int ret;
+    ret = WaitForSingleObject(thread, INFINITE);
+    if (ret && value_ptr)
+        GetExitCodeThread(thread, (void*) value_ptr);
+    return -(!!ret);
+}
+
+int pthread_cond_broadcast(pthread_cond_t *cond)
+{
+    WakeAllConditionVariable(cond);
+    return 0;
+}
+
+int pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+    int ret;
+    ret = CloseHandle(mutex);
+    return -(!ret);
+}
+
+int pthread_cond_destroy(pthread_cond_t *GIT_UNUSED(cond))
+{
+	GIT_UNUSED_ARG(cond);
+    return 0;
+}
+
+int pthread_cond_init(pthread_cond_t *GIT_RESTRICT cond,
+                      const pthread_condattr_t *GIT_RESTRICT GIT_UNUSED(condattr))
+{
+	GIT_UNUSED_ARG(condattr);
+    InitializeConditionVariable(cond);
+    return 0;
+}
+
+int pthread_mutex_init(pthread_mutex_t *GIT_RESTRICT mutex,
+                       const pthread_mutexattr_t *GIT_RESTRICT GIT_UNUSED(mutexattr))
+{
+	GIT_UNUSED_ARG(mutexattr);
+    InitializeCriticalSection(mutex);
+    return 0;
+}
+
+int pthread_num_processors_np(void)
+{
+    DWORD_PTR p, s;
+    int n = 0;
+
+    if (GetProcessAffinityMask(GetCurrentProcess(), &p, &s))
+        for (; p; p >>= 1)
+            n += p&1;
+
+    return n ? n : 1;
+}
+
diff --git a/libgit2/src/win32/pthread.h b/libgit2/src/win32/pthread.h
new file mode 100644
--- /dev/null
+++ b/libgit2/src/win32/pthread.h
@@ -0,0 +1,67 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *  Original code by Ramiro Polla (Public Domain)
+ */
+
+#ifndef GIT_PTHREAD_H
+#define GIT_PTHREAD_H
+
+#include "../common.h"
+
+#if defined (_MSC_VER)
+#	define GIT_RESTRICT __restrict
+#else
+#	define GIT_RESTRICT __restrict__
+#endif
+
+typedef int pthread_mutexattr_t;
+typedef int pthread_condattr_t;
+typedef int pthread_attr_t;
+typedef CRITICAL_SECTION pthread_mutex_t;
+typedef CONDITION_VARIABLE pthread_cond_t;
+typedef HANDLE pthread_t;
+
+#define PTHREAD_MUTEX_INITIALIZER {(void*)-1};
+
+int pthread_create(pthread_t *GIT_RESTRICT,
+                   const pthread_attr_t *GIT_RESTRICT,
+                   void *(*start_routine)(void*), void *__restrict);
+
+int pthread_join(pthread_t, void **);
+
+int pthread_mutex_init(pthread_mutex_t *GIT_RESTRICT, const pthread_mutexattr_t *GIT_RESTRICT);
+int pthread_mutex_destroy(pthread_mutex_t *);
+int pthread_mutex_lock(pthread_mutex_t *);
+int pthread_mutex_unlock(pthread_mutex_t *);
+
+int pthread_cond_init(pthread_cond_t *GIT_RESTRICT, const pthread_condattr_t *GIT_RESTRICT);
+int pthread_cond_destroy(pthread_cond_t *);
+int pthread_cond_broadcast(pthread_cond_t *);
+int pthread_cond_signal(pthread_cond_t *);
+int pthread_cond_wait(pthread_cond_t *GIT_RESTRICT, pthread_mutex_t *GIT_RESTRICT);
+
+int pthread_num_processors_np(void);
+
+#endif
diff --git a/tests/Main.hi b/tests/Main.hi
new file mode 100644
Binary files /dev/null and b/tests/Main.hi differ
diff --git a/tests/Main.hs b/tests/Main.hs
new file mode 100644
--- /dev/null
+++ b/tests/Main.hs
@@ -0,0 +1,15 @@
+module Main where
+import Bindings.Libgit2
+import Foreign
+import Foreign.C.String
+import System.Exit
+import Control.Monad(when)
+import System.Process(system)
+
+main = do
+  alloca $ \ptr -> do
+    system "git init smoke.git" 
+    withCString "smoke.git/.git" $ \str -> do
+      r <- c'git_repository_open ptr str
+      when (r < 0) $ exitWith (ExitFailure 1) 
+      peek ptr >>= c'git_repository_free
diff --git a/tests/Main.hs~ b/tests/Main.hs~
new file mode 100644
--- /dev/null
+++ b/tests/Main.hs~
@@ -0,0 +1,10 @@
+module Main where
+import Bindings.Libgit2
+import Foreign
+import Foreign.C.String
+
+main = do
+  alloca $ \ptr -> do
+    withCString "foobar.git/.git" $ \str -> do
+      c'git_repository_open ptr str
+      peek ptr >>= c'git_repository_free
diff --git a/tests/Main.o b/tests/Main.o
new file mode 100644
Binary files /dev/null and b/tests/Main.o differ
