rugged 0.1.2 → 0.16.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (277) hide show
  1. data/README.md +25 -36
  2. data/Rakefile +20 -98
  3. data/ext/rugged/extconf.rb +44 -4
  4. data/ext/rugged/remote.c +215 -0
  5. data/ext/rugged/rugged.c +171 -0
  6. data/ext/rugged/rugged.h +126 -0
  7. data/ext/rugged/rugged_blob.c +99 -0
  8. data/ext/rugged/rugged_commit.c +224 -0
  9. data/ext/rugged/rugged_config.c +238 -0
  10. data/ext/rugged/rugged_index.c +440 -0
  11. data/ext/rugged/rugged_object.c +203 -0
  12. data/ext/rugged/rugged_reference.c +401 -0
  13. data/ext/rugged/rugged_repo.c +482 -0
  14. data/ext/rugged/rugged_revwalk.c +138 -0
  15. data/ext/rugged/rugged_signature.c +80 -0
  16. data/ext/rugged/rugged_tag.c +216 -0
  17. data/ext/rugged/rugged_tree.c +322 -0
  18. data/ext/rugged/vendor/libgit2-dist.tar.gz +0 -0
  19. data/ext/rugged/vendor/libgit2-dist/deps/http-parser/http_parser.c +1778 -0
  20. data/ext/rugged/vendor/libgit2-dist/deps/http-parser/http_parser.h +267 -0
  21. data/ext/rugged/vendor/libgit2-dist/deps/zlib/adler32.c +169 -0
  22. data/ext/rugged/vendor/libgit2-dist/deps/zlib/crc32.c +442 -0
  23. data/ext/rugged/vendor/libgit2-dist/deps/zlib/crc32.h +441 -0
  24. data/ext/rugged/vendor/libgit2-dist/deps/zlib/deflate.c +1834 -0
  25. data/ext/rugged/vendor/libgit2-dist/deps/zlib/deflate.h +342 -0
  26. data/ext/rugged/vendor/libgit2-dist/deps/zlib/inffast.c +340 -0
  27. data/ext/rugged/vendor/libgit2-dist/deps/zlib/inffast.h +11 -0
  28. data/ext/rugged/vendor/libgit2-dist/deps/zlib/inffixed.h +94 -0
  29. data/ext/rugged/vendor/libgit2-dist/deps/zlib/inflate.c +1480 -0
  30. data/ext/rugged/vendor/libgit2-dist/deps/zlib/inflate.h +122 -0
  31. data/ext/rugged/vendor/libgit2-dist/deps/zlib/inftrees.c +330 -0
  32. data/ext/rugged/vendor/libgit2-dist/deps/zlib/inftrees.h +62 -0
  33. data/ext/rugged/vendor/libgit2-dist/deps/zlib/trees.c +1244 -0
  34. data/ext/rugged/vendor/libgit2-dist/deps/zlib/trees.h +128 -0
  35. data/ext/rugged/vendor/libgit2-dist/deps/zlib/zconf.h +54 -0
  36. data/ext/rugged/vendor/libgit2-dist/deps/zlib/zlib.h +1613 -0
  37. data/ext/rugged/vendor/libgit2-dist/deps/zlib/zutil.c +318 -0
  38. data/ext/rugged/vendor/libgit2-dist/deps/zlib/zutil.h +274 -0
  39. data/ext/rugged/vendor/libgit2-dist/examples/general.c +451 -0
  40. data/ext/rugged/vendor/libgit2-dist/examples/network/common.h +14 -0
  41. data/ext/rugged/vendor/libgit2-dist/examples/network/fetch.c +97 -0
  42. data/ext/rugged/vendor/libgit2-dist/examples/network/git2.c +58 -0
  43. data/ext/rugged/vendor/libgit2-dist/examples/network/index-pack.c +47 -0
  44. data/ext/rugged/vendor/libgit2-dist/examples/network/ls-remote.c +76 -0
  45. data/ext/rugged/vendor/libgit2-dist/examples/showindex.c +43 -0
  46. data/ext/rugged/vendor/libgit2-dist/include/git2.h +44 -0
  47. data/ext/rugged/vendor/libgit2-dist/include/git2/blob.h +120 -0
  48. data/ext/rugged/vendor/libgit2-dist/include/git2/branch.h +15 -0
  49. data/ext/rugged/vendor/libgit2-dist/include/git2/commit.h +263 -0
  50. data/ext/rugged/vendor/libgit2-dist/include/git2/common.h +103 -0
  51. data/ext/rugged/vendor/libgit2-dist/include/git2/config.h +278 -0
  52. data/ext/rugged/vendor/libgit2-dist/include/git2/errors.h +144 -0
  53. data/ext/rugged/vendor/libgit2-dist/include/git2/index.h +306 -0
  54. data/ext/rugged/vendor/libgit2-dist/include/git2/indexer.h +76 -0
  55. data/ext/rugged/vendor/libgit2-dist/include/git2/inttypes.h +305 -0
  56. data/ext/rugged/vendor/libgit2-dist/include/git2/net.h +51 -0
  57. data/ext/rugged/vendor/libgit2-dist/include/git2/object.h +173 -0
  58. data/ext/rugged/vendor/libgit2-dist/include/git2/odb.h +331 -0
  59. data/ext/rugged/vendor/libgit2-dist/include/git2/odb_backend.h +100 -0
  60. data/ext/rugged/vendor/libgit2-dist/include/git2/oid.h +218 -0
  61. data/ext/rugged/vendor/libgit2-dist/include/git2/reflog.h +128 -0
  62. data/ext/rugged/vendor/libgit2-dist/include/git2/refs.h +309 -0
  63. data/ext/rugged/vendor/libgit2-dist/include/git2/refspec.h +60 -0
  64. data/ext/rugged/vendor/libgit2-dist/include/git2/remote.h +176 -0
  65. data/ext/rugged/vendor/libgit2-dist/include/git2/repository.h +290 -0
  66. data/ext/rugged/vendor/libgit2-dist/include/git2/revwalk.h +169 -0
  67. data/ext/rugged/vendor/libgit2-dist/include/git2/signature.h +65 -0
  68. data/ext/rugged/vendor/libgit2-dist/include/git2/status.h +63 -0
  69. data/ext/rugged/vendor/libgit2-dist/include/git2/stdint.h +247 -0
  70. data/ext/rugged/vendor/libgit2-dist/include/git2/tag.h +279 -0
  71. data/ext/rugged/vendor/libgit2-dist/include/git2/threads.h +48 -0
  72. data/ext/rugged/vendor/libgit2-dist/include/git2/tree.h +318 -0
  73. data/ext/rugged/vendor/libgit2-dist/include/git2/types.h +169 -0
  74. data/ext/rugged/vendor/libgit2-dist/include/git2/version.h +15 -0
  75. data/ext/rugged/vendor/libgit2-dist/include/git2/windows.h +59 -0
  76. data/ext/rugged/vendor/libgit2-dist/include/git2/zlib.h +40 -0
  77. data/ext/rugged/vendor/libgit2-dist/src/blob.c +135 -0
  78. data/ext/rugged/vendor/libgit2-dist/src/blob.h +23 -0
  79. data/ext/rugged/vendor/libgit2-dist/src/bswap.h +97 -0
  80. data/ext/rugged/vendor/libgit2-dist/src/buffer.c +113 -0
  81. data/ext/rugged/vendor/libgit2-dist/src/buffer.h +32 -0
  82. data/ext/rugged/vendor/libgit2-dist/src/cache.c +111 -0
  83. data/ext/rugged/vendor/libgit2-dist/src/cache.h +64 -0
  84. data/ext/rugged/vendor/libgit2-dist/src/cc-compat.h +67 -0
  85. data/ext/rugged/vendor/libgit2-dist/src/commit.c +299 -0
  86. data/ext/rugged/vendor/libgit2-dist/src/commit.h +34 -0
  87. data/ext/rugged/vendor/libgit2-dist/src/common.h +64 -0
  88. data/ext/rugged/vendor/libgit2-dist/src/config.c +418 -0
  89. data/ext/rugged/vendor/libgit2-dist/src/config.h +24 -0
  90. data/ext/rugged/vendor/libgit2-dist/src/config_file.c +1210 -0
  91. data/ext/rugged/vendor/libgit2-dist/src/delta-apply.c +115 -0
  92. data/ext/rugged/vendor/libgit2-dist/src/delta-apply.h +33 -0
  93. data/ext/rugged/vendor/libgit2-dist/src/dir.h +47 -0
  94. data/ext/rugged/vendor/libgit2-dist/src/errors.c +104 -0
  95. data/ext/rugged/vendor/libgit2-dist/src/fetch.c +172 -0
  96. data/ext/rugged/vendor/libgit2-dist/src/fetch.h +18 -0
  97. data/ext/rugged/vendor/libgit2-dist/src/filebuf.c +400 -0
  98. data/ext/rugged/vendor/libgit2-dist/src/filebuf.h +72 -0
  99. data/ext/rugged/vendor/libgit2-dist/src/fileops.c +358 -0
  100. data/ext/rugged/vendor/libgit2-dist/src/fileops.h +151 -0
  101. data/ext/rugged/vendor/libgit2-dist/src/global.c +134 -0
  102. data/ext/rugged/vendor/libgit2-dist/src/global.h +24 -0
  103. data/ext/rugged/vendor/libgit2-dist/src/hash.c +74 -0
  104. data/ext/rugged/vendor/libgit2-dist/src/hash.h +29 -0
  105. data/ext/rugged/vendor/libgit2-dist/src/hashtable.c +243 -0
  106. data/ext/rugged/vendor/libgit2-dist/src/hashtable.h +80 -0
  107. data/ext/rugged/vendor/libgit2-dist/src/index.c +918 -0
  108. data/ext/rugged/vendor/libgit2-dist/src/index.h +34 -0
  109. data/ext/rugged/vendor/libgit2-dist/src/indexer.c +401 -0
  110. data/ext/rugged/vendor/libgit2-dist/src/map.h +37 -0
  111. data/ext/rugged/vendor/libgit2-dist/src/mwindow.c +272 -0
  112. data/ext/rugged/vendor/libgit2-dist/src/mwindow.h +45 -0
  113. data/ext/rugged/vendor/libgit2-dist/src/netops.c +198 -0
  114. data/ext/rugged/vendor/libgit2-dist/src/netops.h +36 -0
  115. data/ext/rugged/vendor/libgit2-dist/src/object.c +295 -0
  116. data/ext/rugged/vendor/libgit2-dist/src/odb.c +672 -0
  117. data/ext/rugged/vendor/libgit2-dist/src/odb.h +43 -0
  118. data/ext/rugged/vendor/libgit2-dist/src/odb_loose.c +855 -0
  119. data/ext/rugged/vendor/libgit2-dist/src/odb_pack.c +485 -0
  120. data/ext/rugged/vendor/libgit2-dist/src/oid.c +388 -0
  121. data/ext/rugged/vendor/libgit2-dist/src/pack.c +788 -0
  122. data/ext/rugged/vendor/libgit2-dist/src/pack.h +99 -0
  123. data/ext/rugged/vendor/libgit2-dist/src/path.c +270 -0
  124. data/ext/rugged/vendor/libgit2-dist/src/path.h +84 -0
  125. data/ext/rugged/vendor/libgit2-dist/src/pkt.c +426 -0
  126. data/ext/rugged/vendor/libgit2-dist/src/pkt.h +77 -0
  127. data/ext/rugged/vendor/libgit2-dist/src/posix.c +94 -0
  128. data/ext/rugged/vendor/libgit2-dist/src/posix.h +69 -0
  129. data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.c +70 -0
  130. data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.h +26 -0
  131. data/ext/rugged/vendor/libgit2-dist/src/pqueue.c +141 -0
  132. data/ext/rugged/vendor/libgit2-dist/src/pqueue.h +81 -0
  133. data/ext/rugged/vendor/libgit2-dist/src/protocol.c +50 -0
  134. data/ext/rugged/vendor/libgit2-dist/src/protocol.h +23 -0
  135. data/ext/rugged/vendor/libgit2-dist/src/reflog.c +318 -0
  136. data/ext/rugged/vendor/libgit2-dist/src/reflog.h +34 -0
  137. data/ext/rugged/vendor/libgit2-dist/src/refs.c +1693 -0
  138. data/ext/rugged/vendor/libgit2-dist/src/refs.h +58 -0
  139. data/ext/rugged/vendor/libgit2-dist/src/refspec.c +95 -0
  140. data/ext/rugged/vendor/libgit2-dist/src/refspec.h +23 -0
  141. data/ext/rugged/vendor/libgit2-dist/src/remote.c +339 -0
  142. data/ext/rugged/vendor/libgit2-dist/src/remote.h +25 -0
  143. data/ext/rugged/vendor/libgit2-dist/src/repository.c +849 -0
  144. data/ext/rugged/vendor/libgit2-dist/src/repository.h +60 -0
  145. data/ext/rugged/vendor/libgit2-dist/src/revwalk.c +569 -0
  146. data/ext/rugged/vendor/libgit2-dist/src/sha1.c +280 -0
  147. data/ext/rugged/vendor/libgit2-dist/src/sha1.h +21 -0
  148. data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.c +177 -0
  149. data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.h +18 -0
  150. data/ext/rugged/vendor/libgit2-dist/src/signature.c +335 -0
  151. data/ext/rugged/vendor/libgit2-dist/src/signature.h +18 -0
  152. data/ext/rugged/vendor/libgit2-dist/src/status.c +696 -0
  153. data/ext/rugged/vendor/libgit2-dist/src/tag.c +446 -0
  154. data/ext/rugged/vendor/libgit2-dist/src/tag.h +28 -0
  155. data/ext/rugged/vendor/libgit2-dist/src/thread-utils.c +55 -0
  156. data/ext/rugged/vendor/libgit2-dist/src/thread-utils.h +108 -0
  157. data/ext/rugged/vendor/libgit2-dist/src/transport.c +85 -0
  158. data/ext/rugged/vendor/libgit2-dist/src/transport.h +110 -0
  159. data/ext/rugged/vendor/libgit2-dist/src/transports/git.c +502 -0
  160. data/ext/rugged/vendor/libgit2-dist/src/transports/http.c +756 -0
  161. data/ext/rugged/vendor/libgit2-dist/src/transports/local.c +235 -0
  162. data/ext/rugged/vendor/libgit2-dist/src/tree-cache.c +201 -0
  163. data/ext/rugged/vendor/libgit2-dist/src/tree-cache.h +31 -0
  164. data/ext/rugged/vendor/libgit2-dist/src/tree.c +758 -0
  165. data/ext/rugged/vendor/libgit2-dist/src/tree.h +37 -0
  166. data/ext/rugged/vendor/libgit2-dist/src/tsort.c +365 -0
  167. data/ext/rugged/vendor/libgit2-dist/src/unix/map.c +70 -0
  168. data/ext/rugged/vendor/libgit2-dist/src/unix/posix.h +25 -0
  169. data/ext/rugged/vendor/libgit2-dist/src/util.c +381 -0
  170. data/ext/rugged/vendor/libgit2-dist/src/util.h +137 -0
  171. data/ext/rugged/vendor/libgit2-dist/src/vector.c +174 -0
  172. data/ext/rugged/vendor/libgit2-dist/src/vector.h +45 -0
  173. data/ext/rugged/vendor/libgit2-dist/src/win32/dir.c +115 -0
  174. data/ext/rugged/vendor/libgit2-dist/src/win32/fnmatch.c +180 -0
  175. data/ext/rugged/vendor/libgit2-dist/src/win32/fnmatch.h +27 -0
  176. data/ext/rugged/vendor/libgit2-dist/src/win32/map.c +131 -0
  177. data/ext/rugged/vendor/libgit2-dist/src/win32/mingw-compat.h +24 -0
  178. data/ext/rugged/vendor/libgit2-dist/src/win32/msvc-compat.h +38 -0
  179. data/ext/rugged/vendor/libgit2-dist/src/win32/posix.h +53 -0
  180. data/ext/rugged/vendor/libgit2-dist/src/win32/posix_w32.c +404 -0
  181. data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.c +65 -0
  182. data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.h +40 -0
  183. data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.c +88 -0
  184. data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.h +17 -0
  185. data/ext/rugged/vendor/libgit2-dist/tests-clay/buf/basic.c +29 -0
  186. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay.h +187 -0
  187. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_libgit2.h +28 -0
  188. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_main.c +1073 -0
  189. data/ext/rugged/vendor/libgit2-dist/tests-clay/config/add.c +37 -0
  190. data/ext/rugged/vendor/libgit2-dist/tests-clay/config/new.c +36 -0
  191. data/ext/rugged/vendor/libgit2-dist/tests-clay/config/read.c +209 -0
  192. data/ext/rugged/vendor/libgit2-dist/tests-clay/config/stress.c +39 -0
  193. data/ext/rugged/vendor/libgit2-dist/tests-clay/config/write.c +77 -0
  194. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/dirent.c +222 -0
  195. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/filebuf.c +106 -0
  196. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/oid.c +18 -0
  197. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/path.c +139 -0
  198. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/rmdir.c +50 -0
  199. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/string.c +28 -0
  200. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/strtol.c +37 -0
  201. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/vector.c +66 -0
  202. data/ext/rugged/vendor/libgit2-dist/tests-clay/index/rename.c +60 -0
  203. data/ext/rugged/vendor/libgit2-dist/tests-clay/network/remotes.c +50 -0
  204. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/chars.c +52 -0
  205. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/compare.c +124 -0
  206. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/convert.c +75 -0
  207. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/data.h +323 -0
  208. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/fromstr.c +30 -0
  209. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/hash.c +162 -0
  210. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/short.c +94 -0
  211. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/size.c +13 -0
  212. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/raw/type2string.c +54 -0
  213. data/ext/rugged/vendor/libgit2-dist/tests-clay/object/tree/frompath.c +75 -0
  214. data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/loose.c +84 -0
  215. data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/loose_data.h +522 -0
  216. data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/pack_data.h +151 -0
  217. data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/packed.c +78 -0
  218. data/ext/rugged/vendor/libgit2-dist/tests-clay/odb/sorting.c +71 -0
  219. data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/getters.c +68 -0
  220. data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/init.c +104 -0
  221. data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/open.c +54 -0
  222. data/ext/rugged/vendor/libgit2-dist/tests-clay/status/single.c +38 -0
  223. data/ext/rugged/vendor/libgit2-dist/tests-clay/status/status_data.h +48 -0
  224. data/ext/rugged/vendor/libgit2-dist/tests-clay/status/worktree.c +124 -0
  225. data/ext/rugged/vendor/libgit2-dist/tests/t00-core.c +628 -0
  226. data/ext/rugged/vendor/libgit2-dist/tests/t01-data.h +322 -0
  227. data/ext/rugged/vendor/libgit2-dist/tests/t01-rawobj.c +638 -0
  228. data/ext/rugged/vendor/libgit2-dist/tests/t03-data.h +344 -0
  229. data/ext/rugged/vendor/libgit2-dist/tests/t03-objwrite.c +255 -0
  230. data/ext/rugged/vendor/libgit2-dist/tests/t04-commit.c +788 -0
  231. data/ext/rugged/vendor/libgit2-dist/tests/t05-revwalk.c +140 -0
  232. data/ext/rugged/vendor/libgit2-dist/tests/t06-index.c +219 -0
  233. data/ext/rugged/vendor/libgit2-dist/tests/t07-hashtable.c +192 -0
  234. data/ext/rugged/vendor/libgit2-dist/tests/t08-tag.c +357 -0
  235. data/ext/rugged/vendor/libgit2-dist/tests/t09-tree.c +221 -0
  236. data/ext/rugged/vendor/libgit2-dist/tests/t10-refs.c +1294 -0
  237. data/ext/rugged/vendor/libgit2-dist/tests/t12-repo.c +174 -0
  238. data/ext/rugged/vendor/libgit2-dist/tests/t13-threads.c +41 -0
  239. data/ext/rugged/vendor/libgit2-dist/tests/t17-bufs.c +61 -0
  240. data/ext/rugged/vendor/libgit2-dist/tests/t18-status.c +448 -0
  241. data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.c +310 -0
  242. data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.h +83 -0
  243. data/ext/rugged/vendor/libgit2-dist/tests/test_lib.c +198 -0
  244. data/ext/rugged/vendor/libgit2-dist/tests/test_lib.h +54 -0
  245. data/ext/rugged/vendor/libgit2-dist/tests/test_main.c +89 -0
  246. data/lib/rugged.rb +4 -3
  247. data/lib/rugged/index.rb +0 -8
  248. data/lib/rugged/objects.rb +45 -0
  249. data/lib/rugged/repository.rb +29 -0
  250. data/lib/rugged/tree.rb +16 -6
  251. data/lib/rugged/version.rb +1 -1
  252. data/lib/rugged/walker.rb +5 -0
  253. data/test/blob_test.rb +18 -14
  254. data/test/commit_test.rb +28 -26
  255. data/test/coverage/HEAD.json +1 -0
  256. data/test/coverage/cover.rb +106 -0
  257. data/test/fixtures/testrepo.git/refs/heads/new_name +1 -0
  258. data/test/index_test.rb +101 -78
  259. data/test/lib_test.rb +4 -4
  260. data/test/object_test.rb +3 -3
  261. data/test/reference_test.rb +75 -0
  262. data/test/remote_test.rb +19 -0
  263. data/test/repo_pack_test.rb +4 -4
  264. data/test/repo_test.rb +44 -15
  265. data/test/tag_test.rb +7 -17
  266. data/test/test_helper.rb +24 -5
  267. data/test/tree_test.rb +30 -12
  268. data/test/walker_test.rb +40 -31
  269. metadata +273 -50
  270. data/lib/rugged/person.rb +0 -20
  271. data/lib/rugged/tree_entry.rb +0 -9
  272. data/test/fixtures/testrepo.git/objects/1d/83f106355e4309a293e42ad2a2c4b8bdbe77ae +0 -0
  273. data/test/fixtures/testrepo.git/objects/2f/3321418db5b2a841375b8b70880a8ab5a4148f +0 -0
  274. data/test/fixtures/testrepo.git/objects/36/9b00a7700cca3a506d79e301d6ad8bf735d9ee +0 -3
  275. data/test/fixtures/testrepo.git/objects/3d/b1b5ceace59ff65279757003763046fd4cbbe6 +0 -0
  276. data/test/fixtures/testrepo.git/objects/4c/d1604907792e2c43e03dcec1216f99d63e68c4 +0 -3
  277. data/test/fixtures/testrepo.git/objects/e0/f46d77041c149296549b01ed4a18b02c4b7400 +0 -0
@@ -0,0 +1,80 @@
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_hashtable_h__
8
+ #define INCLUDE_hashtable_h__
9
+
10
+ #include "git2/common.h"
11
+ #include "git2/oid.h"
12
+ #include "git2/odb.h"
13
+ #include "common.h"
14
+
15
+ #define GIT_HASHTABLE_HASHES 3
16
+
17
+ typedef uint32_t (*git_hash_ptr)(const void *, int hash_id);
18
+ typedef int (*git_hash_keyeq_ptr)(const void *key_a, const void *key_b);
19
+
20
+ struct git_hashtable_node {
21
+ const void *key;
22
+ void *value;
23
+ };
24
+
25
+ struct git_hashtable {
26
+ struct git_hashtable_node *nodes;
27
+
28
+ size_t size_mask;
29
+ size_t size;
30
+ size_t key_count;
31
+
32
+ int is_resizing;
33
+
34
+ git_hash_ptr hash;
35
+ git_hash_keyeq_ptr key_equal;
36
+ };
37
+
38
+ typedef struct git_hashtable_node git_hashtable_node;
39
+ typedef struct git_hashtable git_hashtable;
40
+
41
+ git_hashtable *git_hashtable_alloc(size_t min_size,
42
+ git_hash_ptr hash,
43
+ git_hash_keyeq_ptr key_eq);
44
+ void *git_hashtable_lookup(git_hashtable *h, const void *key);
45
+ int git_hashtable_remove(git_hashtable *table, const void *key);
46
+ void git_hashtable_free(git_hashtable *h);
47
+ void git_hashtable_clear(git_hashtable *h);
48
+ int git_hashtable_merge(git_hashtable *self, git_hashtable *other);
49
+
50
+ int git_hashtable_insert2(git_hashtable *h, const void *key, void *value, void **old_value);
51
+
52
+ GIT_INLINE(int) git_hashtable_insert(git_hashtable *h, const void *key, void *value)
53
+ {
54
+ void *_unused;
55
+ return git_hashtable_insert2(h, key, value, &_unused);
56
+ }
57
+
58
+ #define git_hashtable_node_at(nodes, pos) ((git_hashtable_node *)(&nodes[pos]))
59
+
60
+ #define GIT_HASHTABLE_FOREACH(self, pkey, pvalue, code) {\
61
+ git_hashtable *_self = (self);\
62
+ git_hashtable_node *_nodes = _self->nodes;\
63
+ unsigned int _i, _size = _self->size;\
64
+ for (_i = 0; _i < _size; _i ++) {\
65
+ git_hashtable_node *_node = git_hashtable_node_at(_nodes, _i);\
66
+ if (_node->key)\
67
+ {\
68
+ pkey = _node->key;\
69
+ pvalue = _node->value;\
70
+ code;\
71
+ }\
72
+ }\
73
+ }
74
+
75
+ #define GIT_HASHTABLE_FOREACH_DELETE() {\
76
+ _node->key = NULL; _node->value = NULL; _self->key_count--;\
77
+ }
78
+
79
+
80
+ #endif
@@ -0,0 +1,918 @@
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 <stddef.h>
9
+
10
+ #include "common.h"
11
+ #include "repository.h"
12
+ #include "index.h"
13
+ #include "tree-cache.h"
14
+ #include "hash.h"
15
+ #include "git2/odb.h"
16
+ #include "git2/blob.h"
17
+
18
+ #define entry_size(type,len) ((offsetof(type, path) + (len) + 8) & ~7)
19
+ #define short_entry_size(len) entry_size(struct entry_short, len)
20
+ #define long_entry_size(len) entry_size(struct entry_long, len)
21
+
22
+ #define minimal_entry_size (offsetof(struct entry_short, path))
23
+
24
+ static const size_t INDEX_FOOTER_SIZE = GIT_OID_RAWSZ;
25
+ static const size_t INDEX_HEADER_SIZE = 12;
26
+
27
+ static const unsigned int INDEX_VERSION_NUMBER = 2;
28
+ static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
29
+
30
+ static const unsigned int INDEX_HEADER_SIG = 0x44495243;
31
+ static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
32
+ static const char INDEX_EXT_UNMERGED_SIG[] = {'R', 'E', 'U', 'C'};
33
+
34
+ #define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
35
+
36
+ struct index_header {
37
+ uint32_t signature;
38
+ uint32_t version;
39
+ uint32_t entry_count;
40
+ };
41
+
42
+ struct index_extension {
43
+ char signature[4];
44
+ uint32_t extension_size;
45
+ };
46
+
47
+ struct entry_time {
48
+ uint32_t seconds;
49
+ uint32_t nanoseconds;
50
+ };
51
+
52
+ struct entry_short {
53
+ struct entry_time ctime;
54
+ struct entry_time mtime;
55
+ uint32_t dev;
56
+ uint32_t ino;
57
+ uint32_t mode;
58
+ uint32_t uid;
59
+ uint32_t gid;
60
+ uint32_t file_size;
61
+ git_oid oid;
62
+ uint16_t flags;
63
+ char path[1]; /* arbitrary length */
64
+ };
65
+
66
+ struct entry_long {
67
+ struct entry_time ctime;
68
+ struct entry_time mtime;
69
+ uint32_t dev;
70
+ uint32_t ino;
71
+ uint32_t mode;
72
+ uint32_t uid;
73
+ uint32_t gid;
74
+ uint32_t file_size;
75
+ git_oid oid;
76
+ uint16_t flags;
77
+ uint16_t flags_extended;
78
+ char path[1]; /* arbitrary length */
79
+ };
80
+
81
+ /* local declarations */
82
+ static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size);
83
+ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size);
84
+ static int read_header(struct index_header *dest, const void *buffer);
85
+
86
+ static int parse_index(git_index *index, const char *buffer, size_t buffer_size);
87
+ static int is_index_extended(git_index *index);
88
+ static int write_index(git_index *index, git_filebuf *file);
89
+
90
+ static int index_srch(const void *key, const void *array_member)
91
+ {
92
+ const git_index_entry *entry = array_member;
93
+
94
+ return strcmp(key, entry->path);
95
+ }
96
+
97
+ static int index_cmp(const void *a, const void *b)
98
+ {
99
+ const git_index_entry *entry_a = a;
100
+ const git_index_entry *entry_b = b;
101
+
102
+ return strcmp(entry_a->path, entry_b->path);
103
+ }
104
+
105
+ static int unmerged_srch(const void *key, const void *array_member)
106
+ {
107
+ const git_index_entry_unmerged *entry = array_member;
108
+
109
+ return strcmp(key, entry->path);
110
+ }
111
+
112
+ static int unmerged_cmp(const void *a, const void *b)
113
+ {
114
+ const git_index_entry_unmerged *info_a = a;
115
+ const git_index_entry_unmerged *info_b = b;
116
+
117
+ return strcmp(info_a->path, info_b->path);
118
+ }
119
+
120
+ static unsigned int index_create_mode(unsigned int mode)
121
+ {
122
+ if (S_ISLNK(mode))
123
+ return S_IFLNK;
124
+ if (S_ISDIR(mode) || (mode & S_IFMT) == (S_IFLNK | S_IFDIR))
125
+ return (S_IFLNK | S_IFDIR);
126
+ return S_IFREG | ((mode & 0100) ? 0755 : 0644);
127
+ }
128
+
129
+ int git_index_open(git_index **index_out, const char *index_path)
130
+ {
131
+ git_index *index;
132
+
133
+ assert(index_out && index_path);
134
+
135
+ index = git__malloc(sizeof(git_index));
136
+ if (index == NULL)
137
+ return GIT_ENOMEM;
138
+
139
+ memset(index, 0x0, sizeof(git_index));
140
+
141
+ index->index_file_path = git__strdup(index_path);
142
+ if (index->index_file_path == NULL) {
143
+ git__free(index);
144
+ return GIT_ENOMEM;
145
+ }
146
+
147
+ git_vector_init(&index->entries, 32, index_cmp);
148
+
149
+ /* Check if index file is stored on disk already */
150
+ if (git_futils_exists(index->index_file_path) == 0)
151
+ index->on_disk = 1;
152
+
153
+ *index_out = index;
154
+ GIT_REFCOUNT_INC(index);
155
+ return git_index_read(index);
156
+ }
157
+
158
+ static void index_free(git_index *index)
159
+ {
160
+ git_index_clear(index);
161
+ git_vector_free(&index->entries);
162
+ git_vector_free(&index->unmerged);
163
+
164
+ git__free(index->index_file_path);
165
+ git__free(index);
166
+ }
167
+
168
+ void git_index_free(git_index *index)
169
+ {
170
+ if (index == NULL)
171
+ return;
172
+
173
+ GIT_REFCOUNT_DEC(index, index_free);
174
+ }
175
+
176
+ void git_index_clear(git_index *index)
177
+ {
178
+ unsigned int i;
179
+
180
+ assert(index);
181
+
182
+ for (i = 0; i < index->entries.length; ++i) {
183
+ git_index_entry *e;
184
+ e = git_vector_get(&index->entries, i);
185
+ git__free(e->path);
186
+ git__free(e);
187
+ }
188
+
189
+ for (i = 0; i < index->unmerged.length; ++i) {
190
+ git_index_entry_unmerged *e;
191
+ e = git_vector_get(&index->unmerged, i);
192
+ git__free(e->path);
193
+ git__free(e);
194
+ }
195
+
196
+ git_vector_clear(&index->entries);
197
+ git_vector_clear(&index->unmerged);
198
+ index->last_modified = 0;
199
+
200
+ git_tree_cache_free(index->tree);
201
+ index->tree = NULL;
202
+ }
203
+
204
+ int git_index_read(git_index *index)
205
+ {
206
+ int error = GIT_SUCCESS, updated;
207
+ git_fbuffer buffer = GIT_FBUFFER_INIT;
208
+ time_t mtime;
209
+
210
+ assert(index->index_file_path);
211
+
212
+ if (!index->on_disk || git_futils_exists(index->index_file_path) < 0) {
213
+ git_index_clear(index);
214
+ index->on_disk = 0;
215
+ return GIT_SUCCESS;
216
+ }
217
+
218
+ /* We don't want to update the mtime if we fail to parse the index */
219
+ mtime = index->last_modified;
220
+ error = git_futils_readbuffer_updated(&buffer, index->index_file_path, &mtime, &updated);
221
+ if (error < GIT_SUCCESS)
222
+ return git__rethrow(error, "Failed to read index");
223
+
224
+ if (updated) {
225
+ git_index_clear(index);
226
+ error = parse_index(index, buffer.data, buffer.len);
227
+
228
+ if (error == GIT_SUCCESS)
229
+ index->last_modified = mtime;
230
+
231
+ git_futils_freebuffer(&buffer);
232
+ }
233
+
234
+ if (error < GIT_SUCCESS)
235
+ return git__rethrow(error, "Failed to parse index");
236
+ return error;
237
+ }
238
+
239
+ int git_index_write(git_index *index)
240
+ {
241
+ git_filebuf file = GIT_FILEBUF_INIT;
242
+ struct stat indexst;
243
+ int error;
244
+
245
+ git_vector_sort(&index->entries);
246
+
247
+ if ((error = git_filebuf_open(&file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS)) < GIT_SUCCESS)
248
+ return git__rethrow(error, "Failed to write index");
249
+
250
+ if ((error = write_index(index, &file)) < GIT_SUCCESS) {
251
+ git_filebuf_cleanup(&file);
252
+ return git__rethrow(error, "Failed to write index");
253
+ }
254
+
255
+ if ((error = git_filebuf_commit(&file, GIT_INDEX_FILE_MODE)) < GIT_SUCCESS)
256
+ return git__rethrow(error, "Failed to write index");
257
+
258
+ if (p_stat(index->index_file_path, &indexst) == 0) {
259
+ index->last_modified = indexst.st_mtime;
260
+ index->on_disk = 1;
261
+ }
262
+
263
+ return GIT_SUCCESS;
264
+ }
265
+
266
+ unsigned int git_index_entrycount(git_index *index)
267
+ {
268
+ assert(index);
269
+ return index->entries.length;
270
+ }
271
+
272
+ unsigned int git_index_entrycount_unmerged(git_index *index)
273
+ {
274
+ assert(index);
275
+ return index->unmerged.length;
276
+ }
277
+
278
+ git_index_entry *git_index_get(git_index *index, unsigned int n)
279
+ {
280
+ git_vector_sort(&index->entries);
281
+ return git_vector_get(&index->entries, n);
282
+ }
283
+
284
+ static int index_entry_init(git_index_entry **entry_out, git_index *index, const char *rel_path, int stage)
285
+ {
286
+ git_index_entry *entry;
287
+ char full_path[GIT_PATH_MAX];
288
+ struct stat st;
289
+ git_oid oid;
290
+ int error;
291
+ const char *workdir;
292
+
293
+ if (INDEX_OWNER(index) == NULL)
294
+ return git__throw(GIT_EBAREINDEX,
295
+ "Failed to initialize entry. Repository is bare");
296
+
297
+ workdir = git_repository_workdir(INDEX_OWNER(index));
298
+ if (workdir == NULL)
299
+ return git__throw(GIT_EBAREINDEX,
300
+ "Failed to initialize entry. Cannot resolved workdir");
301
+
302
+ git_path_join(full_path, workdir, rel_path);
303
+
304
+ if (p_lstat(full_path, &st) < 0)
305
+ return git__throw(GIT_ENOTFOUND,
306
+ "Failed to initialize entry. '%s' cannot be opened", full_path);
307
+
308
+ if (stage < 0 || stage > 3)
309
+ return git__throw(GIT_ERROR,
310
+ "Failed to initialize entry. Invalid stage %i", stage);
311
+
312
+ /* write the blob to disk and get the oid */
313
+ if ((error = git_blob_create_fromfile(&oid, INDEX_OWNER(index), rel_path)) < GIT_SUCCESS)
314
+ return git__rethrow(error, "Failed to initialize index entry");
315
+
316
+ entry = git__malloc(sizeof(git_index_entry));
317
+ if (!entry)
318
+ return GIT_ENOMEM;
319
+ memset(entry, 0x0, sizeof(git_index_entry));
320
+
321
+ entry->ctime.seconds = (git_time_t)st.st_ctime;
322
+ entry->mtime.seconds = (git_time_t)st.st_mtime;
323
+ /* entry.mtime.nanoseconds = st.st_mtimensec; */
324
+ /* entry.ctime.nanoseconds = st.st_ctimensec; */
325
+ entry->dev= st.st_rdev;
326
+ entry->ino = st.st_ino;
327
+ entry->mode = index_create_mode(st.st_mode);
328
+ entry->uid = st.st_uid;
329
+ entry->gid = st.st_gid;
330
+ entry->file_size = st.st_size;
331
+ entry->oid = oid;
332
+
333
+ entry->flags |= (stage << GIT_IDXENTRY_STAGESHIFT);
334
+ entry->path = git__strdup(rel_path);
335
+ if (entry->path == NULL) {
336
+ git__free(entry);
337
+ return GIT_ENOMEM;
338
+ }
339
+
340
+ *entry_out = entry;
341
+ return GIT_SUCCESS;
342
+ }
343
+
344
+ static git_index_entry *index_entry_dup(const git_index_entry *source_entry)
345
+ {
346
+ git_index_entry *entry;
347
+
348
+ entry = git__malloc(sizeof(git_index_entry));
349
+ if (!entry)
350
+ return NULL;
351
+
352
+ memcpy(entry, source_entry, sizeof(git_index_entry));
353
+
354
+ /* duplicate the path string so we own it */
355
+ entry->path = git__strdup(entry->path);
356
+ if (!entry->path)
357
+ return NULL;
358
+
359
+ return entry;
360
+ }
361
+
362
+ static void index_entry_free(git_index_entry *entry)
363
+ {
364
+ if (!entry)
365
+ return;
366
+ git__free(entry->path);
367
+ git__free(entry);
368
+ }
369
+
370
+ static int index_insert(git_index *index, git_index_entry *entry, int replace)
371
+ {
372
+ size_t path_length;
373
+ int position;
374
+ git_index_entry **entry_array;
375
+
376
+ assert(index && entry);
377
+
378
+ if (entry->path == NULL)
379
+ return git__throw(GIT_EMISSINGOBJDATA, "Failed to insert into index. Entry has no path");
380
+
381
+ /* make sure that the path length flag is correct */
382
+ path_length = strlen(entry->path);
383
+
384
+ entry->flags &= ~GIT_IDXENTRY_NAMEMASK;
385
+
386
+ if (path_length < GIT_IDXENTRY_NAMEMASK)
387
+ entry->flags |= path_length & GIT_IDXENTRY_NAMEMASK;
388
+ else
389
+ entry->flags |= GIT_IDXENTRY_NAMEMASK;;
390
+
391
+ /*
392
+ * replacing is not requested: just insert entry at the end;
393
+ * the index is no longer sorted
394
+ */
395
+ if (!replace) {
396
+ if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS)
397
+ return GIT_ENOMEM;
398
+
399
+ return GIT_SUCCESS;
400
+ }
401
+
402
+ /* look if an entry with this path already exists */
403
+ position = git_index_find(index, entry->path);
404
+
405
+ /*
406
+ * if no entry exists add the entry at the end;
407
+ * the index is no longer sorted
408
+ */
409
+ if (position == GIT_ENOTFOUND) {
410
+ if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS)
411
+ return GIT_ENOMEM;
412
+
413
+ return GIT_SUCCESS;
414
+ }
415
+
416
+ /* exists, replace it */
417
+ entry_array = (git_index_entry **) index->entries.contents;
418
+ git__free(entry_array[position]->path);
419
+ git__free(entry_array[position]);
420
+ entry_array[position] = entry;
421
+
422
+ return GIT_SUCCESS;
423
+ }
424
+
425
+ static int index_add(git_index *index, const char *path, int stage, int replace)
426
+ {
427
+ git_index_entry *entry = NULL;
428
+ int ret;
429
+
430
+ ret = index_entry_init(&entry, index, path, stage);
431
+ if (ret)
432
+ goto err;
433
+
434
+ ret = index_insert(index, entry, replace);
435
+ if (ret)
436
+ goto err;
437
+
438
+ git_tree_cache_invalidate_path(index->tree, entry->path);
439
+
440
+ return ret;
441
+ err:
442
+ index_entry_free(entry);
443
+ return git__rethrow(ret, "Failed to append to index");
444
+ }
445
+
446
+ int git_index_add(git_index *index, const char *path, int stage)
447
+ {
448
+ return index_add(index, path, stage, 1);
449
+ }
450
+
451
+ int git_index_append(git_index *index, const char *path, int stage)
452
+ {
453
+ return index_add(index, path, stage, 0);
454
+ }
455
+
456
+ static int index_add2(git_index *index, const git_index_entry *source_entry,
457
+ int replace)
458
+ {
459
+ git_index_entry *entry = NULL;
460
+ int ret;
461
+
462
+ entry = index_entry_dup(source_entry);
463
+ if (entry == NULL) {
464
+ ret = GIT_ENOMEM;
465
+ goto err;
466
+ }
467
+
468
+ ret = index_insert(index, entry, replace);
469
+ if (ret)
470
+ goto err;
471
+
472
+ git_tree_cache_invalidate_path(index->tree, entry->path);
473
+
474
+ return ret;
475
+ err:
476
+ index_entry_free(entry);
477
+ return git__rethrow(ret, "Failed to append to index");
478
+ }
479
+
480
+ int git_index_add2(git_index *index, const git_index_entry *source_entry)
481
+ {
482
+ return index_add2(index, source_entry, 1);
483
+ }
484
+
485
+ int git_index_append2(git_index *index, const git_index_entry *source_entry)
486
+ {
487
+ return index_add2(index, source_entry, 1);
488
+ }
489
+
490
+ int git_index_remove(git_index *index, int position)
491
+ {
492
+ git_index_entry *entry;
493
+
494
+ git_vector_sort(&index->entries);
495
+ entry = git_vector_get(&index->entries, position);
496
+ if (entry != NULL)
497
+ git_tree_cache_invalidate_path(index->tree, entry->path);
498
+
499
+ return git_vector_remove(&index->entries, (unsigned int)position);
500
+ }
501
+
502
+ int git_index_find(git_index *index, const char *path)
503
+ {
504
+ return git_vector_bsearch2(&index->entries, index_srch, path);
505
+ }
506
+
507
+ void git_index_uniq(git_index *index)
508
+ {
509
+ git_vector_uniq(&index->entries);
510
+ }
511
+
512
+ const git_index_entry_unmerged *git_index_get_unmerged_bypath(git_index *index, const char *path)
513
+ {
514
+ int pos;
515
+ assert(index && path);
516
+
517
+ if (!index->unmerged.length)
518
+ return NULL;
519
+
520
+ if ((pos = git_vector_bsearch2(&index->unmerged, unmerged_srch, path)) < GIT_SUCCESS)
521
+ return NULL;
522
+
523
+ return git_vector_get(&index->unmerged, pos);
524
+ }
525
+
526
+ const git_index_entry_unmerged *git_index_get_unmerged_byindex(git_index *index, unsigned int n)
527
+ {
528
+ assert(index);
529
+ return git_vector_get(&index->unmerged, n);
530
+ }
531
+
532
+ static int read_unmerged(git_index *index, const char *buffer, size_t size)
533
+ {
534
+ const char *endptr;
535
+ size_t len;
536
+ int i;
537
+
538
+ git_vector_init(&index->unmerged, 16, unmerged_cmp);
539
+
540
+ while (size) {
541
+ git_index_entry_unmerged *lost;
542
+
543
+ len = strlen(buffer) + 1;
544
+ if (size <= len)
545
+ return git__throw(GIT_ERROR, "Failed to read unmerged entries");
546
+
547
+ if ((lost = git__malloc(sizeof(git_index_entry_unmerged))) == NULL)
548
+ return GIT_ENOMEM;
549
+
550
+ if (git_vector_insert(&index->unmerged, lost) < GIT_SUCCESS)
551
+ return git__throw(GIT_ERROR, "Failed to read unmerged entries");
552
+
553
+ lost->path = git__strdup(buffer);
554
+ if (!lost->path)
555
+ return GIT_ENOMEM;
556
+
557
+ size -= len;
558
+ buffer += len;
559
+
560
+ for (i = 0; i < 3; i++) {
561
+ int tmp;
562
+
563
+ if (git__strtol32(&tmp, buffer, &endptr, 8) < GIT_SUCCESS ||
564
+ !endptr || endptr == buffer || *endptr || (unsigned)tmp > UINT_MAX)
565
+ return GIT_ERROR;
566
+
567
+ lost->mode[i] = tmp;
568
+
569
+ len = (endptr + 1) - buffer;
570
+ if (size <= len)
571
+ return git__throw(GIT_ERROR, "Failed to read unmerged entries");
572
+
573
+ size -= len;
574
+ buffer += len;
575
+ }
576
+
577
+ for (i = 0; i < 3; i++) {
578
+ if (!lost->mode[i])
579
+ continue;
580
+ if (size < 20)
581
+ return git__throw(GIT_ERROR, "Failed to read unmerged entries");
582
+ git_oid_fromraw(&lost->oid[i], (const unsigned char *) buffer);
583
+ size -= 20;
584
+ buffer += 20;
585
+ }
586
+ }
587
+
588
+ return GIT_SUCCESS;
589
+ }
590
+
591
+ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffer_size)
592
+ {
593
+ size_t path_length, entry_size;
594
+ uint16_t flags_raw;
595
+ const char *path_ptr;
596
+ const struct entry_short *source = buffer;
597
+
598
+ if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
599
+ return 0;
600
+
601
+ memset(dest, 0x0, sizeof(git_index_entry));
602
+
603
+ dest->ctime.seconds = (git_time_t)ntohl(source->ctime.seconds);
604
+ dest->ctime.nanoseconds = ntohl(source->ctime.nanoseconds);
605
+ dest->mtime.seconds = (git_time_t)ntohl(source->mtime.seconds);
606
+ dest->mtime.nanoseconds = ntohl(source->mtime.nanoseconds);
607
+ dest->dev = ntohl(source->dev);
608
+ dest->ino = ntohl(source->ino);
609
+ dest->mode = ntohl(source->mode);
610
+ dest->uid = ntohl(source->uid);
611
+ dest->gid = ntohl(source->gid);
612
+ dest->file_size = ntohl(source->file_size);
613
+ git_oid_cpy(&dest->oid, &source->oid);
614
+ dest->flags = ntohs(source->flags);
615
+
616
+ if (dest->flags & GIT_IDXENTRY_EXTENDED) {
617
+ const struct entry_long *source_l = (const struct entry_long *)source;
618
+ path_ptr = source_l->path;
619
+
620
+ flags_raw = ntohs(source_l->flags_extended);
621
+ memcpy(&dest->flags_extended, &flags_raw, 2);
622
+ } else
623
+ path_ptr = source->path;
624
+
625
+ path_length = dest->flags & GIT_IDXENTRY_NAMEMASK;
626
+
627
+ /* if this is a very long string, we must find its
628
+ * real length without overflowing */
629
+ if (path_length == 0xFFF) {
630
+ const char *path_end;
631
+
632
+ path_end = memchr(path_ptr, '\0', buffer_size);
633
+ if (path_end == NULL)
634
+ return 0;
635
+
636
+ path_length = path_end - path_ptr;
637
+ }
638
+
639
+ if (dest->flags & GIT_IDXENTRY_EXTENDED)
640
+ entry_size = long_entry_size(path_length);
641
+ else
642
+ entry_size = short_entry_size(path_length);
643
+
644
+ if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
645
+ return 0;
646
+
647
+ dest->path = git__strdup(path_ptr);
648
+ assert(dest->path);
649
+
650
+ return entry_size;
651
+ }
652
+
653
+ static int read_header(struct index_header *dest, const void *buffer)
654
+ {
655
+ const struct index_header *source = buffer;
656
+
657
+ dest->signature = ntohl(source->signature);
658
+ if (dest->signature != INDEX_HEADER_SIG)
659
+ return GIT_EOBJCORRUPTED;
660
+
661
+ dest->version = ntohl(source->version);
662
+ if (dest->version != INDEX_VERSION_NUMBER_EXT &&
663
+ dest->version != INDEX_VERSION_NUMBER)
664
+ return GIT_EOBJCORRUPTED;
665
+
666
+ dest->entry_count = ntohl(source->entry_count);
667
+ return GIT_SUCCESS;
668
+ }
669
+
670
+ static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size)
671
+ {
672
+ const struct index_extension *source;
673
+ struct index_extension dest;
674
+ size_t total_size;
675
+
676
+ source = (const struct index_extension *)(buffer);
677
+
678
+ memcpy(dest.signature, source->signature, 4);
679
+ dest.extension_size = ntohl(source->extension_size);
680
+
681
+ total_size = dest.extension_size + sizeof(struct index_extension);
682
+
683
+ if (buffer_size - total_size < INDEX_FOOTER_SIZE)
684
+ return 0;
685
+
686
+ /* optional extension */
687
+ if (dest.signature[0] >= 'A' && dest.signature[0] <= 'Z') {
688
+ /* tree cache */
689
+ if (memcmp(dest.signature, INDEX_EXT_TREECACHE_SIG, 4) == 0) {
690
+ if (git_tree_cache_read(&index->tree, buffer + 8, dest.extension_size) < GIT_SUCCESS)
691
+ return 0;
692
+ } else if (memcmp(dest.signature, INDEX_EXT_UNMERGED_SIG, 4) == 0) {
693
+ if (read_unmerged(index, buffer + 8, dest.extension_size) < GIT_SUCCESS)
694
+ return 0;
695
+ }
696
+ /* else, unsupported extension. We cannot parse this, but we can skip
697
+ * it by returning `total_size */
698
+ } else {
699
+ /* we cannot handle non-ignorable extensions;
700
+ * in fact they aren't even defined in the standard */
701
+ return 0;
702
+ }
703
+
704
+ return total_size;
705
+ }
706
+
707
+ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
708
+ {
709
+ unsigned int i;
710
+ struct index_header header;
711
+ git_oid checksum_calculated, checksum_expected;
712
+
713
+ #define seek_forward(_increase) { \
714
+ if (_increase >= buffer_size) \
715
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to seek forward. Buffer size exceeded"); \
716
+ buffer += _increase; \
717
+ buffer_size -= _increase;\
718
+ }
719
+
720
+ if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE)
721
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Buffer too small");
722
+
723
+ /* Precalculate the SHA1 of the files's contents -- we'll match it to
724
+ * the provided SHA1 in the footer */
725
+ git_hash_buf(&checksum_calculated, buffer, buffer_size - INDEX_FOOTER_SIZE);
726
+
727
+ /* Parse header */
728
+ if (read_header(&header, buffer) < GIT_SUCCESS)
729
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Header is corrupted");
730
+
731
+ seek_forward(INDEX_HEADER_SIZE);
732
+
733
+ git_vector_clear(&index->entries);
734
+
735
+ /* Parse all the entries */
736
+ for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
737
+ size_t entry_size;
738
+ git_index_entry *entry;
739
+
740
+ entry = git__malloc(sizeof(git_index_entry));
741
+ if (entry == NULL)
742
+ return GIT_ENOMEM;
743
+
744
+ entry_size = read_entry(entry, buffer, buffer_size);
745
+
746
+ /* 0 bytes read means an object corruption */
747
+ if (entry_size == 0)
748
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Entry size is zero");
749
+
750
+ if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS)
751
+ return GIT_ENOMEM;
752
+
753
+ seek_forward(entry_size);
754
+ }
755
+
756
+ if (i != header.entry_count)
757
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Header entries changed while parsing");
758
+
759
+ /* There's still space for some extensions! */
760
+ while (buffer_size > INDEX_FOOTER_SIZE) {
761
+ size_t extension_size;
762
+
763
+ extension_size = read_extension(index, buffer, buffer_size);
764
+
765
+ /* see if we have read any bytes from the extension */
766
+ if (extension_size == 0)
767
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Extension size is zero");
768
+
769
+ seek_forward(extension_size);
770
+ }
771
+
772
+ if (buffer_size != INDEX_FOOTER_SIZE)
773
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Buffer size does not match index footer size");
774
+
775
+ /* 160-bit SHA-1 over the content of the index file before this checksum. */
776
+ git_oid_fromraw(&checksum_expected, (const unsigned char *)buffer);
777
+
778
+ if (git_oid_cmp(&checksum_calculated, &checksum_expected) != 0)
779
+ return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Calculated checksum does not match expected checksum");
780
+
781
+ #undef seek_forward
782
+
783
+ /* force sorting in the vector: the entries are
784
+ * assured to be sorted on the index */
785
+ index->entries.sorted = 1;
786
+ return GIT_SUCCESS;
787
+ }
788
+
789
+ static int is_index_extended(git_index *index)
790
+ {
791
+ unsigned int i, extended;
792
+
793
+ extended = 0;
794
+
795
+ for (i = 0; i < index->entries.length; ++i) {
796
+ git_index_entry *entry;
797
+ entry = git_vector_get(&index->entries, i);
798
+ entry->flags &= ~GIT_IDXENTRY_EXTENDED;
799
+ if (entry->flags_extended & GIT_IDXENTRY_EXTENDED_FLAGS) {
800
+ extended++;
801
+ entry->flags |= GIT_IDXENTRY_EXTENDED;
802
+ }
803
+ }
804
+ return extended;
805
+ }
806
+
807
+ static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
808
+ {
809
+ void *mem = NULL;
810
+ struct entry_short *ondisk;
811
+ size_t path_len, disk_size;
812
+ char *path;
813
+
814
+ path_len = strlen(entry->path);
815
+
816
+ if (entry->flags & GIT_IDXENTRY_EXTENDED)
817
+ disk_size = long_entry_size(path_len);
818
+ else
819
+ disk_size = short_entry_size(path_len);
820
+
821
+ if (git_filebuf_reserve(file, &mem, disk_size) < GIT_SUCCESS)
822
+ return GIT_ENOMEM;
823
+
824
+ ondisk = (struct entry_short *)mem;
825
+
826
+ memset(ondisk, 0x0, disk_size);
827
+
828
+ /**
829
+ * Yes, we have to truncate.
830
+ *
831
+ * The on-disk format for Index entries clearly defines
832
+ * the time and size fields to be 4 bytes each -- so even if
833
+ * we store these values with 8 bytes on-memory, they must
834
+ * be truncated to 4 bytes before writing to disk.
835
+ *
836
+ * In 2038 I will be either too dead or too rich to care about this
837
+ */
838
+ ondisk->ctime.seconds = htonl((uint32_t)entry->ctime.seconds);
839
+ ondisk->mtime.seconds = htonl((uint32_t)entry->mtime.seconds);
840
+ ondisk->ctime.nanoseconds = htonl(entry->ctime.nanoseconds);
841
+ ondisk->mtime.nanoseconds = htonl(entry->mtime.nanoseconds);
842
+ ondisk->dev = htonl(entry->dev);
843
+ ondisk->ino = htonl(entry->ino);
844
+ ondisk->mode = htonl(entry->mode);
845
+ ondisk->uid = htonl(entry->uid);
846
+ ondisk->gid = htonl(entry->gid);
847
+ ondisk->file_size = htonl((uint32_t)entry->file_size);
848
+
849
+ git_oid_cpy(&ondisk->oid, &entry->oid);
850
+
851
+ ondisk->flags = htons(entry->flags);
852
+
853
+ if (entry->flags & GIT_IDXENTRY_EXTENDED) {
854
+ struct entry_long *ondisk_ext;
855
+ ondisk_ext = (struct entry_long *)ondisk;
856
+ ondisk_ext->flags_extended = htons(entry->flags_extended);
857
+ path = ondisk_ext->path;
858
+ }
859
+ else
860
+ path = ondisk->path;
861
+
862
+ memcpy(path, entry->path, path_len);
863
+
864
+ return GIT_SUCCESS;
865
+ }
866
+
867
+ static int write_entries(git_index *index, git_filebuf *file)
868
+ {
869
+ unsigned int i;
870
+
871
+ for (i = 0; i < index->entries.length; ++i) {
872
+ git_index_entry *entry;
873
+ entry = git_vector_get(&index->entries, i);
874
+ if (write_disk_entry(file, entry) < GIT_SUCCESS)
875
+ return GIT_ENOMEM;
876
+ }
877
+
878
+ return GIT_SUCCESS;
879
+ }
880
+
881
+ static int write_index(git_index *index, git_filebuf *file)
882
+ {
883
+ int error = GIT_SUCCESS;
884
+ git_oid hash_final;
885
+
886
+ struct index_header header;
887
+
888
+ int is_extended;
889
+
890
+ assert(index && file);
891
+
892
+ is_extended = is_index_extended(index);
893
+
894
+ header.signature = htonl(INDEX_HEADER_SIG);
895
+ header.version = htonl(is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER);
896
+ header.entry_count = htonl(index->entries.length);
897
+
898
+ git_filebuf_write(file, &header, sizeof(struct index_header));
899
+
900
+ error = write_entries(index, file);
901
+ if (error < GIT_SUCCESS)
902
+ return git__rethrow(error, "Failed to write index");
903
+
904
+ /* TODO: write extensions (tree cache) */
905
+
906
+ /* get out the hash for all the contents we've appended to the file */
907
+ git_filebuf_hash(&hash_final, file);
908
+
909
+ /* write it at the end of the file */
910
+ git_filebuf_write(file, hash_final.id, GIT_OID_RAWSZ);
911
+
912
+ return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write index");
913
+ }
914
+
915
+ int git_index_entry_stage(const git_index_entry *entry)
916
+ {
917
+ return (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT;
918
+ }