rugged 0.1.2 → 0.16.0b1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +25 -36
- data/Rakefile +20 -98
- data/ext/rugged/extconf.rb +44 -4
- data/ext/rugged/remote.c +215 -0
- data/ext/rugged/rugged.c +171 -0
- data/ext/rugged/rugged.h +126 -0
- data/ext/rugged/rugged_blob.c +99 -0
- data/ext/rugged/rugged_commit.c +224 -0
- data/ext/rugged/rugged_config.c +238 -0
- data/ext/rugged/rugged_index.c +440 -0
- data/ext/rugged/rugged_object.c +203 -0
- data/ext/rugged/rugged_reference.c +401 -0
- data/ext/rugged/rugged_repo.c +482 -0
- data/ext/rugged/rugged_revwalk.c +138 -0
- data/ext/rugged/rugged_signature.c +80 -0
- data/ext/rugged/rugged_tag.c +216 -0
- data/ext/rugged/rugged_tree.c +322 -0
- data/ext/rugged/vendor/libgit2-dist.tar.gz +0 -0
- data/ext/rugged/vendor/libgit2-dist/deps/http-parser/http_parser.c +1778 -0
- data/ext/rugged/vendor/libgit2-dist/deps/http-parser/http_parser.h +267 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/adler32.c +169 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/crc32.c +442 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/crc32.h +441 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/deflate.c +1834 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/deflate.h +342 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/inffast.c +340 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/inffast.h +11 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/inffixed.h +94 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/inflate.c +1480 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/inflate.h +122 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/inftrees.c +330 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/inftrees.h +62 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/trees.c +1244 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/trees.h +128 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/zconf.h +54 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/zlib.h +1613 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/zutil.c +318 -0
- data/ext/rugged/vendor/libgit2-dist/deps/zlib/zutil.h +274 -0
- data/ext/rugged/vendor/libgit2-dist/examples/general.c +451 -0
- data/ext/rugged/vendor/libgit2-dist/examples/network/common.h +14 -0
- data/ext/rugged/vendor/libgit2-dist/examples/network/fetch.c +97 -0
- data/ext/rugged/vendor/libgit2-dist/examples/network/git2.c +58 -0
- data/ext/rugged/vendor/libgit2-dist/examples/network/index-pack.c +47 -0
- data/ext/rugged/vendor/libgit2-dist/examples/network/ls-remote.c +76 -0
- data/ext/rugged/vendor/libgit2-dist/examples/showindex.c +43 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2.h +44 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/blob.h +120 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/branch.h +15 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/commit.h +263 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/common.h +103 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/config.h +278 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/errors.h +144 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/index.h +306 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/indexer.h +76 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/inttypes.h +305 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/net.h +51 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/object.h +173 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/odb.h +331 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/odb_backend.h +100 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/oid.h +218 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/reflog.h +128 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/refs.h +309 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/refspec.h +60 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/remote.h +176 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/repository.h +290 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/revwalk.h +169 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/signature.h +65 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/status.h +63 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/stdint.h +247 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/tag.h +279 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/threads.h +48 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/tree.h +318 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/types.h +169 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/version.h +15 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/windows.h +59 -0
- data/ext/rugged/vendor/libgit2-dist/include/git2/zlib.h +40 -0
- data/ext/rugged/vendor/libgit2-dist/src/blob.c +135 -0
- data/ext/rugged/vendor/libgit2-dist/src/blob.h +23 -0
- data/ext/rugged/vendor/libgit2-dist/src/bswap.h +97 -0
- data/ext/rugged/vendor/libgit2-dist/src/buffer.c +113 -0
- data/ext/rugged/vendor/libgit2-dist/src/buffer.h +32 -0
- data/ext/rugged/vendor/libgit2-dist/src/cache.c +111 -0
- data/ext/rugged/vendor/libgit2-dist/src/cache.h +64 -0
- data/ext/rugged/vendor/libgit2-dist/src/cc-compat.h +67 -0
- data/ext/rugged/vendor/libgit2-dist/src/commit.c +299 -0
- data/ext/rugged/vendor/libgit2-dist/src/commit.h +34 -0
- data/ext/rugged/vendor/libgit2-dist/src/common.h +64 -0
- data/ext/rugged/vendor/libgit2-dist/src/config.c +418 -0
- data/ext/rugged/vendor/libgit2-dist/src/config.h +24 -0
- data/ext/rugged/vendor/libgit2-dist/src/config_file.c +1210 -0
- data/ext/rugged/vendor/libgit2-dist/src/delta-apply.c +115 -0
- data/ext/rugged/vendor/libgit2-dist/src/delta-apply.h +33 -0
- data/ext/rugged/vendor/libgit2-dist/src/dir.h +47 -0
- data/ext/rugged/vendor/libgit2-dist/src/errors.c +104 -0
- data/ext/rugged/vendor/libgit2-dist/src/fetch.c +172 -0
- data/ext/rugged/vendor/libgit2-dist/src/fetch.h +18 -0
- data/ext/rugged/vendor/libgit2-dist/src/filebuf.c +400 -0
- data/ext/rugged/vendor/libgit2-dist/src/filebuf.h +72 -0
- data/ext/rugged/vendor/libgit2-dist/src/fileops.c +358 -0
- data/ext/rugged/vendor/libgit2-dist/src/fileops.h +151 -0
- data/ext/rugged/vendor/libgit2-dist/src/global.c +134 -0
- data/ext/rugged/vendor/libgit2-dist/src/global.h +24 -0
- data/ext/rugged/vendor/libgit2-dist/src/hash.c +74 -0
- data/ext/rugged/vendor/libgit2-dist/src/hash.h +29 -0
- data/ext/rugged/vendor/libgit2-dist/src/hashtable.c +243 -0
- data/ext/rugged/vendor/libgit2-dist/src/hashtable.h +80 -0
- data/ext/rugged/vendor/libgit2-dist/src/index.c +918 -0
- data/ext/rugged/vendor/libgit2-dist/src/index.h +34 -0
- data/ext/rugged/vendor/libgit2-dist/src/indexer.c +401 -0
- data/ext/rugged/vendor/libgit2-dist/src/map.h +37 -0
- data/ext/rugged/vendor/libgit2-dist/src/mwindow.c +272 -0
- data/ext/rugged/vendor/libgit2-dist/src/mwindow.h +45 -0
- data/ext/rugged/vendor/libgit2-dist/src/netops.c +198 -0
- data/ext/rugged/vendor/libgit2-dist/src/netops.h +36 -0
- data/ext/rugged/vendor/libgit2-dist/src/object.c +295 -0
- data/ext/rugged/vendor/libgit2-dist/src/odb.c +672 -0
- data/ext/rugged/vendor/libgit2-dist/src/odb.h +43 -0
- data/ext/rugged/vendor/libgit2-dist/src/odb_loose.c +855 -0
- data/ext/rugged/vendor/libgit2-dist/src/odb_pack.c +485 -0
- data/ext/rugged/vendor/libgit2-dist/src/oid.c +388 -0
- data/ext/rugged/vendor/libgit2-dist/src/pack.c +788 -0
- data/ext/rugged/vendor/libgit2-dist/src/pack.h +99 -0
- data/ext/rugged/vendor/libgit2-dist/src/path.c +270 -0
- data/ext/rugged/vendor/libgit2-dist/src/path.h +84 -0
- data/ext/rugged/vendor/libgit2-dist/src/pkt.c +426 -0
- data/ext/rugged/vendor/libgit2-dist/src/pkt.h +77 -0
- data/ext/rugged/vendor/libgit2-dist/src/posix.c +94 -0
- data/ext/rugged/vendor/libgit2-dist/src/posix.h +69 -0
- data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.c +70 -0
- data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.h +26 -0
- data/ext/rugged/vendor/libgit2-dist/src/pqueue.c +141 -0
- data/ext/rugged/vendor/libgit2-dist/src/pqueue.h +81 -0
- data/ext/rugged/vendor/libgit2-dist/src/protocol.c +50 -0
- data/ext/rugged/vendor/libgit2-dist/src/protocol.h +23 -0
- data/ext/rugged/vendor/libgit2-dist/src/reflog.c +318 -0
- data/ext/rugged/vendor/libgit2-dist/src/reflog.h +34 -0
- data/ext/rugged/vendor/libgit2-dist/src/refs.c +1693 -0
- data/ext/rugged/vendor/libgit2-dist/src/refs.h +58 -0
- data/ext/rugged/vendor/libgit2-dist/src/refspec.c +95 -0
- data/ext/rugged/vendor/libgit2-dist/src/refspec.h +23 -0
- data/ext/rugged/vendor/libgit2-dist/src/remote.c +339 -0
- data/ext/rugged/vendor/libgit2-dist/src/remote.h +25 -0
- data/ext/rugged/vendor/libgit2-dist/src/repository.c +849 -0
- data/ext/rugged/vendor/libgit2-dist/src/repository.h +60 -0
- data/ext/rugged/vendor/libgit2-dist/src/revwalk.c +569 -0
- data/ext/rugged/vendor/libgit2-dist/src/sha1.c +280 -0
- data/ext/rugged/vendor/libgit2-dist/src/sha1.h +21 -0
- data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.c +177 -0
- data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.h +18 -0
- data/ext/rugged/vendor/libgit2-dist/src/signature.c +335 -0
- data/ext/rugged/vendor/libgit2-dist/src/signature.h +18 -0
- data/ext/rugged/vendor/libgit2-dist/src/status.c +696 -0
- data/ext/rugged/vendor/libgit2-dist/src/tag.c +446 -0
- data/ext/rugged/vendor/libgit2-dist/src/tag.h +28 -0
- data/ext/rugged/vendor/libgit2-dist/src/thread-utils.c +55 -0
- data/ext/rugged/vendor/libgit2-dist/src/thread-utils.h +108 -0
- data/ext/rugged/vendor/libgit2-dist/src/transport.c +85 -0
- data/ext/rugged/vendor/libgit2-dist/src/transport.h +110 -0
- data/ext/rugged/vendor/libgit2-dist/src/transports/git.c +502 -0
- data/ext/rugged/vendor/libgit2-dist/src/transports/http.c +756 -0
- data/ext/rugged/vendor/libgit2-dist/src/transports/local.c +235 -0
- data/ext/rugged/vendor/libgit2-dist/src/tree-cache.c +201 -0
- data/ext/rugged/vendor/libgit2-dist/src/tree-cache.h +31 -0
- data/ext/rugged/vendor/libgit2-dist/src/tree.c +758 -0
- data/ext/rugged/vendor/libgit2-dist/src/tree.h +37 -0
- data/ext/rugged/vendor/libgit2-dist/src/tsort.c +365 -0
- data/ext/rugged/vendor/libgit2-dist/src/unix/map.c +70 -0
- data/ext/rugged/vendor/libgit2-dist/src/unix/posix.h +25 -0
- data/ext/rugged/vendor/libgit2-dist/src/util.c +381 -0
- data/ext/rugged/vendor/libgit2-dist/src/util.h +137 -0
- data/ext/rugged/vendor/libgit2-dist/src/vector.c +174 -0
- data/ext/rugged/vendor/libgit2-dist/src/vector.h +45 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/dir.c +115 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/fnmatch.c +180 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/fnmatch.h +27 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/map.c +131 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/mingw-compat.h +24 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/msvc-compat.h +38 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/posix.h +53 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/posix_w32.c +404 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.c +65 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.h +40 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.c +88 -0
- data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.h +17 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/buf/basic.c +29 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/clay.h +187 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_libgit2.h +28 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_main.c +1073 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/config/add.c +37 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/config/new.c +36 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/config/read.c +209 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/config/stress.c +39 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/config/write.c +77 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/dirent.c +222 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/filebuf.c +106 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/oid.c +18 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/path.c +139 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/rmdir.c +50 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/string.c +28 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/strtol.c +37 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/core/vector.c +66 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/index/rename.c +60 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/network/remotes.c +50 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/chars.c +52 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/compare.c +124 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/convert.c +75 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/data.h +323 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/fromstr.c +30 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/hash.c +162 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/short.c +94 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/size.c +13 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/type2string.c +54 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/object/tree/frompath.c +75 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/loose.c +84 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/loose_data.h +522 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/pack_data.h +151 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/packed.c +78 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/sorting.c +71 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/getters.c +68 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/init.c +104 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/open.c +54 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/status/single.c +38 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/status/status_data.h +48 -0
- data/ext/rugged/vendor/libgit2-dist/tests-clay/status/worktree.c +124 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t00-core.c +628 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t01-data.h +322 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t01-rawobj.c +638 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t03-data.h +344 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t03-objwrite.c +255 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t04-commit.c +788 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t05-revwalk.c +140 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t06-index.c +219 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t07-hashtable.c +192 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t08-tag.c +357 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t09-tree.c +221 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t10-refs.c +1294 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t12-repo.c +174 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t13-threads.c +41 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t17-bufs.c +61 -0
- data/ext/rugged/vendor/libgit2-dist/tests/t18-status.c +448 -0
- data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.c +310 -0
- data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.h +83 -0
- data/ext/rugged/vendor/libgit2-dist/tests/test_lib.c +198 -0
- data/ext/rugged/vendor/libgit2-dist/tests/test_lib.h +54 -0
- data/ext/rugged/vendor/libgit2-dist/tests/test_main.c +89 -0
- data/lib/rugged.rb +4 -3
- data/lib/rugged/index.rb +0 -8
- data/lib/rugged/objects.rb +45 -0
- data/lib/rugged/repository.rb +29 -0
- data/lib/rugged/tree.rb +16 -6
- data/lib/rugged/version.rb +1 -1
- data/lib/rugged/walker.rb +5 -0
- data/test/blob_test.rb +18 -14
- data/test/commit_test.rb +28 -26
- data/test/coverage/HEAD.json +1 -0
- data/test/coverage/cover.rb +106 -0
- data/test/fixtures/testrepo.git/refs/heads/new_name +1 -0
- data/test/index_test.rb +101 -78
- data/test/lib_test.rb +4 -4
- data/test/object_test.rb +3 -3
- data/test/reference_test.rb +75 -0
- data/test/remote_test.rb +19 -0
- data/test/repo_pack_test.rb +4 -4
- data/test/repo_test.rb +44 -15
- data/test/tag_test.rb +7 -17
- data/test/test_helper.rb +24 -5
- data/test/tree_test.rb +30 -12
- data/test/walker_test.rb +40 -31
- metadata +273 -50
- data/lib/rugged/person.rb +0 -20
- data/lib/rugged/tree_entry.rb +0 -9
- data/test/fixtures/testrepo.git/objects/1d/83f106355e4309a293e42ad2a2c4b8bdbe77ae +0 -0
- data/test/fixtures/testrepo.git/objects/2f/3321418db5b2a841375b8b70880a8ab5a4148f +0 -0
- data/test/fixtures/testrepo.git/objects/36/9b00a7700cca3a506d79e301d6ad8bf735d9ee +0 -3
- data/test/fixtures/testrepo.git/objects/3d/b1b5ceace59ff65279757003763046fd4cbbe6 +0 -0
- data/test/fixtures/testrepo.git/objects/4c/d1604907792e2c43e03dcec1216f99d63e68c4 +0 -3
- data/test/fixtures/testrepo.git/objects/e0/f46d77041c149296549b01ed4a18b02c4b7400 +0 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2009-2011 the libgit2 contributors
|
3
|
+
*
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
6
|
+
*/
|
7
|
+
#ifndef INCLUDE_odb_h__
|
8
|
+
#define INCLUDE_odb_h__
|
9
|
+
|
10
|
+
#include "git2/odb.h"
|
11
|
+
#include "git2/oid.h"
|
12
|
+
#include "git2/types.h"
|
13
|
+
|
14
|
+
#include "vector.h"
|
15
|
+
#include "cache.h"
|
16
|
+
|
17
|
+
#define GIT_OBJECTS_DIR "objects/"
|
18
|
+
#define GIT_OBJECT_DIR_MODE 0777
|
19
|
+
#define GIT_OBJECT_FILE_MODE 0444
|
20
|
+
|
21
|
+
/* DO NOT EXPORT */
|
22
|
+
typedef struct {
|
23
|
+
void *data; /**< Raw, decompressed object data. */
|
24
|
+
size_t len; /**< Total number of bytes in data. */
|
25
|
+
git_otype type; /**< Type of this object. */
|
26
|
+
} git_rawobj;
|
27
|
+
|
28
|
+
/* EXPORT */
|
29
|
+
struct git_odb_object {
|
30
|
+
git_cached_obj cached;
|
31
|
+
git_rawobj raw;
|
32
|
+
};
|
33
|
+
|
34
|
+
/* EXPORT */
|
35
|
+
struct git_odb {
|
36
|
+
git_refcount rc;
|
37
|
+
git_vector backends;
|
38
|
+
git_cache cache;
|
39
|
+
};
|
40
|
+
|
41
|
+
int git_odb__hash_obj(git_oid *id, git_rawobj *obj);
|
42
|
+
|
43
|
+
#endif
|
@@ -0,0 +1,855 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2009-2011 the libgit2 contributors
|
3
|
+
*
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include "common.h"
|
9
|
+
#include "git2/zlib.h"
|
10
|
+
#include "git2/object.h"
|
11
|
+
#include "git2/oid.h"
|
12
|
+
#include "fileops.h"
|
13
|
+
#include "hash.h"
|
14
|
+
#include "odb.h"
|
15
|
+
#include "delta-apply.h"
|
16
|
+
#include "filebuf.h"
|
17
|
+
|
18
|
+
#include "git2/odb_backend.h"
|
19
|
+
#include "git2/types.h"
|
20
|
+
|
21
|
+
typedef struct { /* object header data */
|
22
|
+
git_otype type; /* object type */
|
23
|
+
size_t size; /* object size */
|
24
|
+
} obj_hdr;
|
25
|
+
|
26
|
+
typedef struct {
|
27
|
+
git_odb_stream stream;
|
28
|
+
git_filebuf fbuf;
|
29
|
+
int finished;
|
30
|
+
} loose_writestream;
|
31
|
+
|
32
|
+
typedef struct loose_backend {
|
33
|
+
git_odb_backend parent;
|
34
|
+
|
35
|
+
int object_zlib_level; /** loose object zlib compression level. */
|
36
|
+
int fsync_object_files; /** loose object file fsync flag. */
|
37
|
+
char *objects_dir;
|
38
|
+
} loose_backend;
|
39
|
+
|
40
|
+
/* State structure for exploring directories,
|
41
|
+
* in order to locate objects matching a short oid.
|
42
|
+
*/
|
43
|
+
typedef struct {
|
44
|
+
size_t dir_len;
|
45
|
+
unsigned char short_oid[GIT_OID_HEXSZ]; /* hex formatted oid to match */
|
46
|
+
unsigned int short_oid_len;
|
47
|
+
int found; /* number of matching
|
48
|
+
* objects already found */
|
49
|
+
unsigned char res_oid[GIT_OID_HEXSZ]; /* hex formatted oid of
|
50
|
+
* the object found */
|
51
|
+
} loose_locate_object_state;
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
/***********************************************************
|
56
|
+
*
|
57
|
+
* MISCELANEOUS HELPER FUNCTIONS
|
58
|
+
*
|
59
|
+
***********************************************************/
|
60
|
+
|
61
|
+
static size_t object_file_name(char *name, size_t n, char *dir, const git_oid *id)
|
62
|
+
{
|
63
|
+
size_t len = strlen(dir);
|
64
|
+
|
65
|
+
/* check length: 43 = 40 hex sha1 chars + 2 * '/' + '\0' */
|
66
|
+
if (len+43 > n)
|
67
|
+
return len+43;
|
68
|
+
|
69
|
+
/* the object dir: eg $GIT_DIR/objects */
|
70
|
+
strcpy(name, dir);
|
71
|
+
if (name[len-1] != '/')
|
72
|
+
name[len++] = '/';
|
73
|
+
|
74
|
+
/* loose object filename: aa/aaa... (41 bytes) */
|
75
|
+
git_oid_pathfmt(&name[len], id);
|
76
|
+
name[len+41] = '\0';
|
77
|
+
|
78
|
+
return 0;
|
79
|
+
}
|
80
|
+
|
81
|
+
|
82
|
+
static size_t get_binary_object_header(obj_hdr *hdr, git_fbuffer *obj)
|
83
|
+
{
|
84
|
+
unsigned char c;
|
85
|
+
unsigned char *data = obj->data;
|
86
|
+
size_t shift, size, used = 0;
|
87
|
+
|
88
|
+
if (obj->len == 0)
|
89
|
+
return 0;
|
90
|
+
|
91
|
+
c = data[used++];
|
92
|
+
hdr->type = (c >> 4) & 7;
|
93
|
+
|
94
|
+
size = c & 15;
|
95
|
+
shift = 4;
|
96
|
+
while (c & 0x80) {
|
97
|
+
if (obj->len <= used)
|
98
|
+
return 0;
|
99
|
+
if (sizeof(size_t) * 8 <= shift)
|
100
|
+
return 0;
|
101
|
+
c = data[used++];
|
102
|
+
size += (c & 0x7f) << shift;
|
103
|
+
shift += 7;
|
104
|
+
}
|
105
|
+
hdr->size = size;
|
106
|
+
|
107
|
+
return used;
|
108
|
+
}
|
109
|
+
|
110
|
+
static size_t get_object_header(obj_hdr *hdr, unsigned char *data)
|
111
|
+
{
|
112
|
+
char c, typename[10];
|
113
|
+
size_t size, used = 0;
|
114
|
+
|
115
|
+
/*
|
116
|
+
* type name string followed by space.
|
117
|
+
*/
|
118
|
+
while ((c = data[used]) != ' ') {
|
119
|
+
typename[used++] = c;
|
120
|
+
if (used >= sizeof(typename))
|
121
|
+
return 0;
|
122
|
+
}
|
123
|
+
typename[used] = 0;
|
124
|
+
if (used == 0)
|
125
|
+
return 0;
|
126
|
+
hdr->type = git_object_string2type(typename);
|
127
|
+
used++; /* consume the space */
|
128
|
+
|
129
|
+
/*
|
130
|
+
* length follows immediately in decimal (without
|
131
|
+
* leading zeros).
|
132
|
+
*/
|
133
|
+
size = data[used++] - '0';
|
134
|
+
if (size > 9)
|
135
|
+
return 0;
|
136
|
+
if (size) {
|
137
|
+
while ((c = data[used]) != '\0') {
|
138
|
+
size_t d = c - '0';
|
139
|
+
if (d > 9)
|
140
|
+
break;
|
141
|
+
used++;
|
142
|
+
size = size * 10 + d;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
hdr->size = size;
|
146
|
+
|
147
|
+
/*
|
148
|
+
* the length must be followed by a zero byte
|
149
|
+
*/
|
150
|
+
if (data[used++] != '\0')
|
151
|
+
return 0;
|
152
|
+
|
153
|
+
return used;
|
154
|
+
}
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
/***********************************************************
|
159
|
+
*
|
160
|
+
* ZLIB RELATED FUNCTIONS
|
161
|
+
*
|
162
|
+
***********************************************************/
|
163
|
+
|
164
|
+
static void init_stream(z_stream *s, void *out, size_t len)
|
165
|
+
{
|
166
|
+
memset(s, 0, sizeof(*s));
|
167
|
+
s->next_out = out;
|
168
|
+
s->avail_out = (uInt)len;
|
169
|
+
}
|
170
|
+
|
171
|
+
static void set_stream_input(z_stream *s, void *in, size_t len)
|
172
|
+
{
|
173
|
+
s->next_in = in;
|
174
|
+
s->avail_in = (uInt)len;
|
175
|
+
}
|
176
|
+
|
177
|
+
static void set_stream_output(z_stream *s, void *out, size_t len)
|
178
|
+
{
|
179
|
+
s->next_out = out;
|
180
|
+
s->avail_out = (uInt)len;
|
181
|
+
}
|
182
|
+
|
183
|
+
|
184
|
+
static int start_inflate(z_stream *s, git_fbuffer *obj, void *out, size_t len)
|
185
|
+
{
|
186
|
+
int status;
|
187
|
+
|
188
|
+
init_stream(s, out, len);
|
189
|
+
set_stream_input(s, obj->data, obj->len);
|
190
|
+
|
191
|
+
if ((status = inflateInit(s)) < Z_OK)
|
192
|
+
return status;
|
193
|
+
|
194
|
+
return inflate(s, 0);
|
195
|
+
}
|
196
|
+
|
197
|
+
static int finish_inflate(z_stream *s)
|
198
|
+
{
|
199
|
+
int status = Z_OK;
|
200
|
+
|
201
|
+
while (status == Z_OK)
|
202
|
+
status = inflate(s, Z_FINISH);
|
203
|
+
|
204
|
+
inflateEnd(s);
|
205
|
+
|
206
|
+
if ((status != Z_STREAM_END) || (s->avail_in != 0))
|
207
|
+
return git__throw(GIT_ERROR, "Failed to finish inflation. Stream aborted prematurely");
|
208
|
+
|
209
|
+
return GIT_SUCCESS;
|
210
|
+
}
|
211
|
+
|
212
|
+
static int is_zlib_compressed_data(unsigned char *data)
|
213
|
+
{
|
214
|
+
unsigned int w;
|
215
|
+
|
216
|
+
w = ((unsigned int)(data[0]) << 8) + data[1];
|
217
|
+
return (data[0] & 0x8F) == 0x08 && !(w % 31);
|
218
|
+
}
|
219
|
+
|
220
|
+
static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
|
221
|
+
{
|
222
|
+
z_stream zs;
|
223
|
+
int status = Z_OK;
|
224
|
+
|
225
|
+
memset(&zs, 0x0, sizeof(zs));
|
226
|
+
|
227
|
+
zs.next_out = out;
|
228
|
+
zs.avail_out = (uInt)outlen;
|
229
|
+
|
230
|
+
zs.next_in = in;
|
231
|
+
zs.avail_in = (uInt)inlen;
|
232
|
+
|
233
|
+
if (inflateInit(&zs) < Z_OK)
|
234
|
+
return git__throw(GIT_ERROR, "Failed to inflate buffer");
|
235
|
+
|
236
|
+
while (status == Z_OK)
|
237
|
+
status = inflate(&zs, Z_FINISH);
|
238
|
+
|
239
|
+
inflateEnd(&zs);
|
240
|
+
|
241
|
+
if ((status != Z_STREAM_END) /*|| (zs.avail_in != 0) */)
|
242
|
+
return git__throw(GIT_ERROR, "Failed to inflate buffer. Stream aborted prematurely");
|
243
|
+
|
244
|
+
if (zs.total_out != outlen)
|
245
|
+
return git__throw(GIT_ERROR, "Failed to inflate buffer. Stream aborted prematurely");
|
246
|
+
|
247
|
+
return GIT_SUCCESS;
|
248
|
+
}
|
249
|
+
|
250
|
+
static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
|
251
|
+
{
|
252
|
+
unsigned char *buf, *head = hb;
|
253
|
+
size_t tail;
|
254
|
+
|
255
|
+
/*
|
256
|
+
* allocate a buffer to hold the inflated data and copy the
|
257
|
+
* initial sequence of inflated data from the tail of the
|
258
|
+
* head buffer, if any.
|
259
|
+
*/
|
260
|
+
if ((buf = git__malloc(hdr->size + 1)) == NULL) {
|
261
|
+
inflateEnd(s);
|
262
|
+
return NULL;
|
263
|
+
}
|
264
|
+
tail = s->total_out - used;
|
265
|
+
if (used > 0 && tail > 0) {
|
266
|
+
if (tail > hdr->size)
|
267
|
+
tail = hdr->size;
|
268
|
+
memcpy(buf, head + used, tail);
|
269
|
+
}
|
270
|
+
used = tail;
|
271
|
+
|
272
|
+
/*
|
273
|
+
* inflate the remainder of the object data, if any
|
274
|
+
*/
|
275
|
+
if (hdr->size < used)
|
276
|
+
inflateEnd(s);
|
277
|
+
else {
|
278
|
+
set_stream_output(s, buf + used, hdr->size - used);
|
279
|
+
if (finish_inflate(s)) {
|
280
|
+
git__free(buf);
|
281
|
+
return NULL;
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
return buf;
|
286
|
+
}
|
287
|
+
|
288
|
+
/*
|
289
|
+
* At one point, there was a loose object format that was intended to
|
290
|
+
* mimic the format used in pack-files. This was to allow easy copying
|
291
|
+
* of loose object data into packs. This format is no longer used, but
|
292
|
+
* we must still read it.
|
293
|
+
*/
|
294
|
+
static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_fbuffer *obj)
|
295
|
+
{
|
296
|
+
unsigned char *in, *buf;
|
297
|
+
obj_hdr hdr;
|
298
|
+
size_t len, used;
|
299
|
+
|
300
|
+
/*
|
301
|
+
* read the object header, which is an (uncompressed)
|
302
|
+
* binary encoding of the object type and size.
|
303
|
+
*/
|
304
|
+
if ((used = get_binary_object_header(&hdr, obj)) == 0)
|
305
|
+
return git__throw(GIT_ERROR, "Failed to inflate loose object. Object has no header");
|
306
|
+
|
307
|
+
if (!git_object_typeisloose(hdr.type))
|
308
|
+
return git__throw(GIT_ERROR, "Failed to inflate loose object. Wrong object type");
|
309
|
+
|
310
|
+
/*
|
311
|
+
* allocate a buffer and inflate the data into it
|
312
|
+
*/
|
313
|
+
buf = git__malloc(hdr.size + 1);
|
314
|
+
if (!buf)
|
315
|
+
return GIT_ENOMEM;
|
316
|
+
|
317
|
+
in = ((unsigned char *)obj->data) + used;
|
318
|
+
len = obj->len - used;
|
319
|
+
if (inflate_buffer(in, len, buf, hdr.size)) {
|
320
|
+
git__free(buf);
|
321
|
+
return git__throw(GIT_ERROR, "Failed to inflate loose object. Could not inflate buffer");
|
322
|
+
}
|
323
|
+
buf[hdr.size] = '\0';
|
324
|
+
|
325
|
+
out->data = buf;
|
326
|
+
out->len = hdr.size;
|
327
|
+
out->type = hdr.type;
|
328
|
+
|
329
|
+
return GIT_SUCCESS;
|
330
|
+
}
|
331
|
+
|
332
|
+
static int inflate_disk_obj(git_rawobj *out, git_fbuffer *obj)
|
333
|
+
{
|
334
|
+
unsigned char head[64], *buf;
|
335
|
+
z_stream zs;
|
336
|
+
obj_hdr hdr;
|
337
|
+
size_t used;
|
338
|
+
|
339
|
+
/*
|
340
|
+
* check for a pack-like loose object
|
341
|
+
*/
|
342
|
+
if (!is_zlib_compressed_data(obj->data))
|
343
|
+
return inflate_packlike_loose_disk_obj(out, obj);
|
344
|
+
|
345
|
+
/*
|
346
|
+
* inflate the initial part of the io buffer in order
|
347
|
+
* to parse the object header (type and size).
|
348
|
+
*/
|
349
|
+
if (start_inflate(&zs, obj, head, sizeof(head)) < Z_OK)
|
350
|
+
return git__throw(GIT_ERROR, "Failed to inflate disk object. Could not inflate buffer");
|
351
|
+
|
352
|
+
if ((used = get_object_header(&hdr, head)) == 0)
|
353
|
+
return git__throw(GIT_ERROR, "Failed to inflate disk object. Object has no header");
|
354
|
+
|
355
|
+
if (!git_object_typeisloose(hdr.type))
|
356
|
+
return git__throw(GIT_ERROR, "Failed to inflate disk object. Wrong object type");
|
357
|
+
|
358
|
+
/*
|
359
|
+
* allocate a buffer and inflate the object data into it
|
360
|
+
* (including the initial sequence in the head buffer).
|
361
|
+
*/
|
362
|
+
if ((buf = inflate_tail(&zs, head, used, &hdr)) == NULL)
|
363
|
+
return GIT_ENOMEM;
|
364
|
+
buf[hdr.size] = '\0';
|
365
|
+
|
366
|
+
out->data = buf;
|
367
|
+
out->len = hdr.size;
|
368
|
+
out->type = hdr.type;
|
369
|
+
|
370
|
+
return GIT_SUCCESS;
|
371
|
+
}
|
372
|
+
|
373
|
+
|
374
|
+
|
375
|
+
|
376
|
+
|
377
|
+
|
378
|
+
/***********************************************************
|
379
|
+
*
|
380
|
+
* ODB OBJECT READING & WRITING
|
381
|
+
*
|
382
|
+
* Backend for the public API; read headers and full objects
|
383
|
+
* from the ODB. Write raw data to the ODB.
|
384
|
+
*
|
385
|
+
***********************************************************/
|
386
|
+
|
387
|
+
static int read_loose(git_rawobj *out, const char *loc)
|
388
|
+
{
|
389
|
+
int error;
|
390
|
+
git_fbuffer obj = GIT_FBUFFER_INIT;
|
391
|
+
|
392
|
+
assert(out && loc);
|
393
|
+
|
394
|
+
out->data = NULL;
|
395
|
+
out->len = 0;
|
396
|
+
out->type = GIT_OBJ_BAD;
|
397
|
+
|
398
|
+
if (git_futils_readbuffer(&obj, loc) < 0)
|
399
|
+
return git__throw(GIT_ENOTFOUND, "Failed to read loose object. File not found");
|
400
|
+
|
401
|
+
error = inflate_disk_obj(out, &obj);
|
402
|
+
git_futils_freebuffer(&obj);
|
403
|
+
|
404
|
+
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to read loose object");
|
405
|
+
}
|
406
|
+
|
407
|
+
static int read_header_loose(git_rawobj *out, const char *loc)
|
408
|
+
{
|
409
|
+
int error = GIT_SUCCESS, z_return = Z_ERRNO, read_bytes;
|
410
|
+
git_file fd;
|
411
|
+
z_stream zs;
|
412
|
+
obj_hdr header_obj;
|
413
|
+
unsigned char raw_buffer[16], inflated_buffer[64];
|
414
|
+
|
415
|
+
assert(out && loc);
|
416
|
+
|
417
|
+
out->data = NULL;
|
418
|
+
|
419
|
+
if ((fd = p_open(loc, O_RDONLY)) < 0)
|
420
|
+
return git__throw(GIT_ENOTFOUND, "Failed to read loose object header. File not found");
|
421
|
+
|
422
|
+
init_stream(&zs, inflated_buffer, sizeof(inflated_buffer));
|
423
|
+
|
424
|
+
if (inflateInit(&zs) < Z_OK) {
|
425
|
+
error = GIT_EZLIB;
|
426
|
+
goto cleanup;
|
427
|
+
}
|
428
|
+
|
429
|
+
do {
|
430
|
+
if ((read_bytes = read(fd, raw_buffer, sizeof(raw_buffer))) > 0) {
|
431
|
+
set_stream_input(&zs, raw_buffer, read_bytes);
|
432
|
+
z_return = inflate(&zs, 0);
|
433
|
+
} else {
|
434
|
+
z_return = Z_STREAM_END;
|
435
|
+
break;
|
436
|
+
}
|
437
|
+
} while (z_return == Z_OK);
|
438
|
+
|
439
|
+
if ((z_return != Z_STREAM_END && z_return != Z_BUF_ERROR)
|
440
|
+
|| get_object_header(&header_obj, inflated_buffer) == 0
|
441
|
+
|| git_object_typeisloose(header_obj.type) == 0) {
|
442
|
+
error = GIT_EOBJCORRUPTED;
|
443
|
+
goto cleanup;
|
444
|
+
}
|
445
|
+
|
446
|
+
out->len = header_obj.size;
|
447
|
+
out->type = header_obj.type;
|
448
|
+
|
449
|
+
cleanup:
|
450
|
+
finish_inflate(&zs);
|
451
|
+
p_close(fd);
|
452
|
+
|
453
|
+
if (error < GIT_SUCCESS)
|
454
|
+
return git__throw(error, "Failed to read loose object header. Header is corrupted");
|
455
|
+
|
456
|
+
return GIT_SUCCESS;
|
457
|
+
}
|
458
|
+
|
459
|
+
static int locate_object(char *object_location, loose_backend *backend, const git_oid *oid)
|
460
|
+
{
|
461
|
+
object_file_name(object_location, GIT_PATH_MAX, backend->objects_dir, oid);
|
462
|
+
return git_futils_exists(object_location);
|
463
|
+
}
|
464
|
+
|
465
|
+
/* Explore an entry of a directory and see if it matches a short oid */
|
466
|
+
static int fn_locate_object_short_oid(void *state, char *pathbuf) {
|
467
|
+
loose_locate_object_state *sstate = (loose_locate_object_state *)state;
|
468
|
+
|
469
|
+
size_t pathbuf_len = strlen(pathbuf);
|
470
|
+
if (pathbuf_len - sstate->dir_len != GIT_OID_HEXSZ - 2) {
|
471
|
+
/* Entry cannot be an object. Continue to next entry */
|
472
|
+
return GIT_SUCCESS;
|
473
|
+
}
|
474
|
+
|
475
|
+
if (!git_futils_exists(pathbuf) && git_futils_isdir(pathbuf)) {
|
476
|
+
/* We are already in the directory matching the 2 first hex characters,
|
477
|
+
* compare the first ncmp characters of the oids */
|
478
|
+
if (!memcmp(sstate->short_oid + 2,
|
479
|
+
(unsigned char *)pathbuf + sstate->dir_len,
|
480
|
+
sstate->short_oid_len - 2)) {
|
481
|
+
|
482
|
+
if (!sstate->found) {
|
483
|
+
sstate->res_oid[0] = sstate->short_oid[0];
|
484
|
+
sstate->res_oid[1] = sstate->short_oid[1];
|
485
|
+
memcpy(sstate->res_oid+2, pathbuf+sstate->dir_len, GIT_OID_HEXSZ-2);
|
486
|
+
}
|
487
|
+
sstate->found++;
|
488
|
+
}
|
489
|
+
}
|
490
|
+
if (sstate->found > 1)
|
491
|
+
return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Ambiguous sha1 prefix within loose objects");
|
492
|
+
|
493
|
+
return GIT_SUCCESS;
|
494
|
+
}
|
495
|
+
|
496
|
+
/* Locate an object matching a given short oid */
|
497
|
+
static int locate_object_short_oid(char *object_location, git_oid *res_oid, loose_backend *backend, const git_oid *short_oid, unsigned int len)
|
498
|
+
{
|
499
|
+
char *objects_dir = backend->objects_dir;
|
500
|
+
size_t dir_len = strlen(objects_dir);
|
501
|
+
loose_locate_object_state state;
|
502
|
+
int error;
|
503
|
+
|
504
|
+
if (dir_len+43 > GIT_PATH_MAX)
|
505
|
+
return git__throw(GIT_ERROR, "Failed to locate object from short oid. Object path too long");
|
506
|
+
|
507
|
+
strcpy(object_location, objects_dir);
|
508
|
+
|
509
|
+
/* Add a separator if not already there */
|
510
|
+
if (object_location[dir_len-1] != '/')
|
511
|
+
object_location[dir_len++] = '/';
|
512
|
+
|
513
|
+
/* Convert raw oid to hex formatted oid */
|
514
|
+
git_oid_fmt((char *)state.short_oid, short_oid);
|
515
|
+
/* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
|
516
|
+
sprintf(object_location+dir_len, "%.2s/", state.short_oid);
|
517
|
+
|
518
|
+
/* Check that directory exists */
|
519
|
+
if (git_futils_exists(object_location) || git_futils_isdir(object_location))
|
520
|
+
return git__throw(GIT_ENOTFOUND, "Failed to locate object from short oid. Object not found");
|
521
|
+
|
522
|
+
state.dir_len = dir_len+3;
|
523
|
+
state.short_oid_len = len;
|
524
|
+
state.found = 0;
|
525
|
+
/* Explore directory to find a unique object matching short_oid */
|
526
|
+
error = git_futils_direach(object_location, GIT_PATH_MAX, fn_locate_object_short_oid, &state);
|
527
|
+
if (error) {
|
528
|
+
return git__rethrow(error, "Failed to locate object from short oid");
|
529
|
+
}
|
530
|
+
if (!state.found) {
|
531
|
+
return git__throw(GIT_ENOTFOUND, "Failed to locate object from short oid. Object not found");
|
532
|
+
}
|
533
|
+
|
534
|
+
/* Convert obtained hex formatted oid to raw */
|
535
|
+
error = git_oid_fromstr(res_oid, (char *)state.res_oid);
|
536
|
+
if (error) {
|
537
|
+
return git__rethrow(error, "Failed to locate object from short oid");
|
538
|
+
}
|
539
|
+
|
540
|
+
/* Update the location according to the oid obtained */
|
541
|
+
git_oid_pathfmt(object_location+dir_len, res_oid);
|
542
|
+
|
543
|
+
return GIT_SUCCESS;
|
544
|
+
}
|
545
|
+
|
546
|
+
|
547
|
+
|
548
|
+
|
549
|
+
|
550
|
+
|
551
|
+
|
552
|
+
|
553
|
+
|
554
|
+
/***********************************************************
|
555
|
+
*
|
556
|
+
* LOOSE BACKEND PUBLIC API
|
557
|
+
*
|
558
|
+
* Implement the git_odb_backend API calls
|
559
|
+
*
|
560
|
+
***********************************************************/
|
561
|
+
|
562
|
+
static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
|
563
|
+
{
|
564
|
+
char object_path[GIT_PATH_MAX];
|
565
|
+
git_rawobj raw;
|
566
|
+
int error;
|
567
|
+
|
568
|
+
assert(backend && oid);
|
569
|
+
|
570
|
+
raw.len = 0;
|
571
|
+
raw.type = GIT_OBJ_BAD;
|
572
|
+
|
573
|
+
if (locate_object(object_path, (loose_backend *)backend, oid) < 0)
|
574
|
+
return git__throw(GIT_ENOTFOUND, "Failed to read loose backend header. Object not found");
|
575
|
+
|
576
|
+
if ((error = read_header_loose(&raw, object_path)) < GIT_SUCCESS)
|
577
|
+
return error;
|
578
|
+
|
579
|
+
*len_p = raw.len;
|
580
|
+
*type_p = raw.type;
|
581
|
+
return GIT_SUCCESS;
|
582
|
+
}
|
583
|
+
|
584
|
+
static int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
|
585
|
+
{
|
586
|
+
char object_path[GIT_PATH_MAX];
|
587
|
+
git_rawobj raw;
|
588
|
+
int error;
|
589
|
+
|
590
|
+
assert(backend && oid);
|
591
|
+
|
592
|
+
if (locate_object(object_path, (loose_backend *)backend, oid) < 0)
|
593
|
+
return git__throw(GIT_ENOTFOUND, "Failed to read loose backend. Object not found");
|
594
|
+
|
595
|
+
if ((error = read_loose(&raw, object_path)) < GIT_SUCCESS)
|
596
|
+
return git__rethrow(error, "Failed to read loose backend");
|
597
|
+
|
598
|
+
*buffer_p = raw.data;
|
599
|
+
*len_p = raw.len;
|
600
|
+
*type_p = raw.type;
|
601
|
+
|
602
|
+
return GIT_SUCCESS;
|
603
|
+
}
|
604
|
+
|
605
|
+
static int loose_backend__read_prefix(
|
606
|
+
git_oid *out_oid,
|
607
|
+
void **buffer_p,
|
608
|
+
size_t *len_p,
|
609
|
+
git_otype *type_p,
|
610
|
+
git_odb_backend *backend,
|
611
|
+
const git_oid *short_oid,
|
612
|
+
unsigned int len)
|
613
|
+
{
|
614
|
+
if (len < GIT_OID_MINPREFIXLEN)
|
615
|
+
return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Failed to read loose backend. Prefix length is lower than %d.", GIT_OID_MINPREFIXLEN);
|
616
|
+
|
617
|
+
if (len >= GIT_OID_HEXSZ) {
|
618
|
+
/* We can fall back to regular read method */
|
619
|
+
int error = loose_backend__read(buffer_p, len_p, type_p, backend, short_oid);
|
620
|
+
if (error == GIT_SUCCESS)
|
621
|
+
git_oid_cpy(out_oid, short_oid);
|
622
|
+
|
623
|
+
return error;
|
624
|
+
} else {
|
625
|
+
char object_path[GIT_PATH_MAX];
|
626
|
+
git_rawobj raw;
|
627
|
+
int error;
|
628
|
+
|
629
|
+
assert(backend && short_oid);
|
630
|
+
|
631
|
+
if ((error = locate_object_short_oid(object_path, out_oid, (loose_backend *)backend, short_oid, len)) < 0) {
|
632
|
+
return git__rethrow(error, "Failed to read loose backend");
|
633
|
+
}
|
634
|
+
|
635
|
+
if ((error = read_loose(&raw, object_path)) < GIT_SUCCESS)
|
636
|
+
return git__rethrow(error, "Failed to read loose backend");
|
637
|
+
|
638
|
+
*buffer_p = raw.data;
|
639
|
+
*len_p = raw.len;
|
640
|
+
*type_p = raw.type;
|
641
|
+
}
|
642
|
+
|
643
|
+
return GIT_SUCCESS;
|
644
|
+
}
|
645
|
+
|
646
|
+
static int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
|
647
|
+
{
|
648
|
+
char object_path[GIT_PATH_MAX];
|
649
|
+
|
650
|
+
assert(backend && oid);
|
651
|
+
|
652
|
+
return locate_object(object_path, (loose_backend *)backend, oid) == GIT_SUCCESS;
|
653
|
+
}
|
654
|
+
|
655
|
+
static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
|
656
|
+
{
|
657
|
+
loose_writestream *stream = (loose_writestream *)_stream;
|
658
|
+
loose_backend *backend = (loose_backend *)_stream->backend;
|
659
|
+
|
660
|
+
int error;
|
661
|
+
char final_path[GIT_PATH_MAX];
|
662
|
+
|
663
|
+
if ((error = git_filebuf_hash(oid, &stream->fbuf)) < GIT_SUCCESS)
|
664
|
+
return git__rethrow(error, "Failed to write loose backend");
|
665
|
+
|
666
|
+
if (object_file_name(final_path, sizeof(final_path), backend->objects_dir, oid))
|
667
|
+
return GIT_ENOMEM;
|
668
|
+
|
669
|
+
if ((error = git_futils_mkpath2file(final_path, GIT_OBJECT_DIR_MODE)) < GIT_SUCCESS)
|
670
|
+
return git__rethrow(error, "Failed to write loose backend");
|
671
|
+
|
672
|
+
stream->finished = 1;
|
673
|
+
|
674
|
+
/*
|
675
|
+
* Don't try to add an existing object to the repository. This
|
676
|
+
* is what git does and allows us to sidestep the fact that
|
677
|
+
* we're not allowed to overwrite a read-only file on Windows.
|
678
|
+
*/
|
679
|
+
if (git_futils_exists(final_path) == GIT_SUCCESS) {
|
680
|
+
git_filebuf_cleanup(&stream->fbuf);
|
681
|
+
return GIT_SUCCESS;
|
682
|
+
}
|
683
|
+
|
684
|
+
return git_filebuf_commit_at(&stream->fbuf, final_path, GIT_OBJECT_FILE_MODE);
|
685
|
+
}
|
686
|
+
|
687
|
+
static int loose_backend__stream_write(git_odb_stream *_stream, const char *data, size_t len)
|
688
|
+
{
|
689
|
+
loose_writestream *stream = (loose_writestream *)_stream;
|
690
|
+
return git_filebuf_write(&stream->fbuf, data, len);
|
691
|
+
}
|
692
|
+
|
693
|
+
static void loose_backend__stream_free(git_odb_stream *_stream)
|
694
|
+
{
|
695
|
+
loose_writestream *stream = (loose_writestream *)_stream;
|
696
|
+
|
697
|
+
if (!stream->finished)
|
698
|
+
git_filebuf_cleanup(&stream->fbuf);
|
699
|
+
|
700
|
+
git__free(stream);
|
701
|
+
}
|
702
|
+
|
703
|
+
static int format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type)
|
704
|
+
{
|
705
|
+
const char *type_str = git_object_type2string(obj_type);
|
706
|
+
int len = snprintf(hdr, n, "%s %"PRIuZ, type_str, obj_len);
|
707
|
+
|
708
|
+
assert(len > 0); /* otherwise snprintf() is broken */
|
709
|
+
assert(((size_t) len) < n); /* otherwise the caller is broken! */
|
710
|
+
|
711
|
+
if (len < 0 || ((size_t) len) >= n)
|
712
|
+
return git__throw(GIT_ERROR, "Failed to format object header. Length is out of bounds");
|
713
|
+
return len+1;
|
714
|
+
}
|
715
|
+
|
716
|
+
static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, size_t length, git_otype type)
|
717
|
+
{
|
718
|
+
loose_backend *backend;
|
719
|
+
loose_writestream *stream;
|
720
|
+
|
721
|
+
char hdr[64], tmp_path[GIT_PATH_MAX];
|
722
|
+
int hdrlen;
|
723
|
+
int error;
|
724
|
+
|
725
|
+
assert(_backend);
|
726
|
+
|
727
|
+
backend = (loose_backend *)_backend;
|
728
|
+
*stream_out = NULL;
|
729
|
+
|
730
|
+
hdrlen = format_object_header(hdr, sizeof(hdr), length, type);
|
731
|
+
if (hdrlen < GIT_SUCCESS)
|
732
|
+
return git__throw(GIT_EOBJCORRUPTED, "Failed to create loose backend stream. Object is corrupted");
|
733
|
+
|
734
|
+
stream = git__calloc(1, sizeof(loose_writestream));
|
735
|
+
if (stream == NULL)
|
736
|
+
return GIT_ENOMEM;
|
737
|
+
|
738
|
+
stream->stream.backend = _backend;
|
739
|
+
stream->stream.read = NULL; /* read only */
|
740
|
+
stream->stream.write = &loose_backend__stream_write;
|
741
|
+
stream->stream.finalize_write = &loose_backend__stream_fwrite;
|
742
|
+
stream->stream.free = &loose_backend__stream_free;
|
743
|
+
stream->stream.mode = GIT_STREAM_WRONLY;
|
744
|
+
|
745
|
+
git_path_join(tmp_path, backend->objects_dir, "tmp_object");
|
746
|
+
|
747
|
+
error = git_filebuf_open(&stream->fbuf, tmp_path,
|
748
|
+
GIT_FILEBUF_HASH_CONTENTS |
|
749
|
+
GIT_FILEBUF_TEMPORARY |
|
750
|
+
(backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT));
|
751
|
+
|
752
|
+
if (error < GIT_SUCCESS) {
|
753
|
+
git__free(stream);
|
754
|
+
return git__rethrow(error, "Failed to create loose backend stream");
|
755
|
+
}
|
756
|
+
|
757
|
+
error = stream->stream.write((git_odb_stream *)stream, hdr, hdrlen);
|
758
|
+
if (error < GIT_SUCCESS) {
|
759
|
+
git_filebuf_cleanup(&stream->fbuf);
|
760
|
+
git__free(stream);
|
761
|
+
return git__rethrow(error, "Failed to create loose backend stream");
|
762
|
+
}
|
763
|
+
|
764
|
+
*stream_out = (git_odb_stream *)stream;
|
765
|
+
return GIT_SUCCESS;
|
766
|
+
}
|
767
|
+
|
768
|
+
static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const void *data, size_t len, git_otype type)
|
769
|
+
{
|
770
|
+
int error, header_len;
|
771
|
+
char final_path[GIT_PATH_MAX], header[64];
|
772
|
+
git_filebuf fbuf = GIT_FILEBUF_INIT;
|
773
|
+
loose_backend *backend;
|
774
|
+
|
775
|
+
backend = (loose_backend *)_backend;
|
776
|
+
|
777
|
+
/* prepare the header for the file */
|
778
|
+
{
|
779
|
+
header_len = format_object_header(header, sizeof(header), len, type);
|
780
|
+
if (header_len < GIT_SUCCESS)
|
781
|
+
return GIT_EOBJCORRUPTED;
|
782
|
+
}
|
783
|
+
|
784
|
+
git_path_join(final_path, backend->objects_dir, "tmp_object");
|
785
|
+
|
786
|
+
error = git_filebuf_open(&fbuf, final_path,
|
787
|
+
GIT_FILEBUF_HASH_CONTENTS |
|
788
|
+
GIT_FILEBUF_TEMPORARY |
|
789
|
+
(backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT));
|
790
|
+
|
791
|
+
if (error < GIT_SUCCESS)
|
792
|
+
return error;
|
793
|
+
|
794
|
+
git_filebuf_write(&fbuf, header, header_len);
|
795
|
+
git_filebuf_write(&fbuf, data, len);
|
796
|
+
git_filebuf_hash(oid, &fbuf);
|
797
|
+
|
798
|
+
if ((error = object_file_name(final_path, sizeof(final_path), backend->objects_dir, oid)) < GIT_SUCCESS)
|
799
|
+
goto cleanup;
|
800
|
+
|
801
|
+
if ((error = git_futils_mkpath2file(final_path, GIT_OBJECT_DIR_MODE)) < GIT_SUCCESS)
|
802
|
+
goto cleanup;
|
803
|
+
|
804
|
+
return git_filebuf_commit_at(&fbuf, final_path, GIT_OBJECT_FILE_MODE);
|
805
|
+
|
806
|
+
cleanup:
|
807
|
+
git_filebuf_cleanup(&fbuf);
|
808
|
+
return error;
|
809
|
+
}
|
810
|
+
|
811
|
+
static void loose_backend__free(git_odb_backend *_backend)
|
812
|
+
{
|
813
|
+
loose_backend *backend;
|
814
|
+
assert(_backend);
|
815
|
+
backend = (loose_backend *)_backend;
|
816
|
+
|
817
|
+
git__free(backend->objects_dir);
|
818
|
+
git__free(backend);
|
819
|
+
}
|
820
|
+
|
821
|
+
int git_odb_backend_loose(
|
822
|
+
git_odb_backend **backend_out,
|
823
|
+
const char *objects_dir,
|
824
|
+
int compression_level,
|
825
|
+
int do_fsync)
|
826
|
+
{
|
827
|
+
loose_backend *backend;
|
828
|
+
|
829
|
+
backend = git__calloc(1, sizeof(loose_backend));
|
830
|
+
if (backend == NULL)
|
831
|
+
return GIT_ENOMEM;
|
832
|
+
|
833
|
+
backend->objects_dir = git__strdup(objects_dir);
|
834
|
+
if (backend->objects_dir == NULL) {
|
835
|
+
git__free(backend);
|
836
|
+
return GIT_ENOMEM;
|
837
|
+
}
|
838
|
+
|
839
|
+
if (compression_level < 0)
|
840
|
+
compression_level = Z_BEST_SPEED;
|
841
|
+
|
842
|
+
backend->object_zlib_level = compression_level;
|
843
|
+
backend->fsync_object_files = do_fsync;
|
844
|
+
|
845
|
+
backend->parent.read = &loose_backend__read;
|
846
|
+
backend->parent.write = &loose_backend__write;
|
847
|
+
backend->parent.read_prefix = &loose_backend__read_prefix;
|
848
|
+
backend->parent.read_header = &loose_backend__read_header;
|
849
|
+
backend->parent.writestream = &loose_backend__stream;
|
850
|
+
backend->parent.exists = &loose_backend__exists;
|
851
|
+
backend->parent.free = &loose_backend__free;
|
852
|
+
|
853
|
+
*backend_out = (git_odb_backend *)backend;
|
854
|
+
return GIT_SUCCESS;
|
855
|
+
}
|