rugged 0.16.0 → 0.17.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (392) hide show
  1. data/README.md +373 -243
  2. data/Rakefile +22 -0
  3. data/ext/rugged/extconf.rb +9 -6
  4. data/ext/rugged/rugged.c +123 -31
  5. data/ext/rugged/rugged.h +11 -10
  6. data/ext/rugged/rugged_blob.c +181 -18
  7. data/ext/rugged/rugged_commit.c +196 -18
  8. data/ext/rugged/rugged_config.c +94 -5
  9. data/ext/rugged/rugged_object.c +54 -1
  10. data/ext/rugged/rugged_reference.c +203 -15
  11. data/ext/rugged/{remote.c → rugged_remote.c} +35 -10
  12. data/ext/rugged/rugged_repo.c +323 -81
  13. data/ext/rugged/rugged_revwalk.c +57 -4
  14. data/ext/rugged/rugged_signature.c +3 -3
  15. data/ext/rugged/rugged_tag.c +72 -1
  16. data/ext/rugged/rugged_tree.c +70 -2
  17. data/ext/rugged/vendor/libgit2-dist/deps/regex/config.h +7 -0
  18. data/ext/rugged/vendor/libgit2-dist/deps/regex/regcomp.c +3856 -0
  19. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex.c +85 -0
  20. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex.h +582 -0
  21. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex_internal.c +1744 -0
  22. data/ext/rugged/vendor/libgit2-dist/deps/regex/regex_internal.h +810 -0
  23. data/ext/rugged/vendor/libgit2-dist/deps/regex/regexec.c +4369 -0
  24. data/ext/rugged/vendor/libgit2-dist/examples/diff.c +238 -0
  25. data/ext/rugged/vendor/libgit2-dist/examples/general.c +4 -4
  26. data/ext/rugged/vendor/libgit2-dist/examples/network/fetch.c +101 -85
  27. data/ext/rugged/vendor/libgit2-dist/examples/network/git2.c +7 -3
  28. data/ext/rugged/vendor/libgit2-dist/examples/network/index-pack.c +80 -25
  29. data/ext/rugged/vendor/libgit2-dist/examples/network/ls-remote.c +6 -6
  30. data/ext/rugged/vendor/libgit2-dist/include/git2/attr.h +224 -0
  31. data/ext/rugged/vendor/libgit2-dist/include/git2/blob.h +59 -5
  32. data/ext/rugged/vendor/libgit2-dist/include/git2/branch.h +114 -7
  33. data/ext/rugged/vendor/libgit2-dist/include/git2/commit.h +14 -7
  34. data/ext/rugged/vendor/libgit2-dist/include/git2/common.h +4 -3
  35. data/ext/rugged/vendor/libgit2-dist/include/git2/config.h +105 -27
  36. data/ext/rugged/vendor/libgit2-dist/include/git2/diff.h +409 -0
  37. data/ext/rugged/vendor/libgit2-dist/include/git2/errors.h +47 -82
  38. data/ext/rugged/vendor/libgit2-dist/include/git2/index.h +25 -10
  39. data/ext/rugged/vendor/libgit2-dist/include/git2/indexer.h +46 -1
  40. data/ext/rugged/vendor/libgit2-dist/include/git2/merge.h +35 -0
  41. data/ext/rugged/vendor/libgit2-dist/include/git2/net.h +1 -1
  42. data/ext/rugged/vendor/libgit2-dist/include/git2/notes.h +139 -0
  43. data/ext/rugged/vendor/libgit2-dist/include/git2/object.h +5 -5
  44. data/ext/rugged/vendor/libgit2-dist/include/git2/odb.h +13 -13
  45. data/ext/rugged/vendor/libgit2-dist/include/git2/odb_backend.h +8 -8
  46. data/ext/rugged/vendor/libgit2-dist/include/git2/oid.h +14 -9
  47. data/ext/rugged/vendor/libgit2-dist/include/git2/reflog.h +5 -5
  48. data/ext/rugged/vendor/libgit2-dist/include/git2/refs.h +37 -17
  49. data/ext/rugged/vendor/libgit2-dist/include/git2/refspec.h +17 -9
  50. data/ext/rugged/vendor/libgit2-dist/include/git2/remote.h +83 -16
  51. data/ext/rugged/vendor/libgit2-dist/include/git2/repository.h +24 -10
  52. data/ext/rugged/vendor/libgit2-dist/include/git2/reset.h +44 -0
  53. data/ext/rugged/vendor/libgit2-dist/include/git2/revparse.h +36 -0
  54. data/ext/rugged/vendor/libgit2-dist/include/git2/revwalk.h +74 -6
  55. data/ext/rugged/vendor/libgit2-dist/include/git2/signature.h +3 -3
  56. data/ext/rugged/vendor/libgit2-dist/include/git2/status.h +120 -19
  57. data/ext/rugged/vendor/libgit2-dist/include/git2/submodule.h +103 -0
  58. data/ext/rugged/vendor/libgit2-dist/include/git2/tag.h +28 -10
  59. data/ext/rugged/vendor/libgit2-dist/include/git2/threads.h +1 -1
  60. data/ext/rugged/vendor/libgit2-dist/include/git2/tree.h +13 -13
  61. data/ext/rugged/vendor/libgit2-dist/include/git2/types.h +16 -2
  62. data/ext/rugged/vendor/libgit2-dist/include/git2/version.h +3 -3
  63. data/ext/rugged/vendor/libgit2-dist/include/git2/windows.h +1 -1
  64. data/ext/rugged/vendor/libgit2-dist/include/git2.h +7 -2
  65. data/ext/rugged/vendor/libgit2-dist/src/attr.c +677 -0
  66. data/ext/rugged/vendor/libgit2-dist/src/attr.h +56 -0
  67. data/ext/rugged/vendor/libgit2-dist/src/attr_file.c +609 -0
  68. data/ext/rugged/vendor/libgit2-dist/src/attr_file.h +145 -0
  69. data/ext/rugged/vendor/libgit2-dist/src/blob.c +213 -60
  70. data/ext/rugged/vendor/libgit2-dist/src/blob.h +2 -1
  71. data/ext/rugged/vendor/libgit2-dist/src/branch.c +208 -0
  72. data/ext/rugged/vendor/libgit2-dist/src/branch.h +17 -0
  73. data/ext/rugged/vendor/libgit2-dist/src/bswap.h +1 -1
  74. data/ext/rugged/vendor/libgit2-dist/src/buffer.c +395 -46
  75. data/ext/rugged/vendor/libgit2-dist/src/buffer.h +112 -9
  76. data/ext/rugged/vendor/libgit2-dist/src/cache.c +37 -49
  77. data/ext/rugged/vendor/libgit2-dist/src/cache.h +7 -17
  78. data/ext/rugged/vendor/libgit2-dist/src/cc-compat.h +18 -16
  79. data/ext/rugged/vendor/libgit2-dist/src/commit.c +56 -90
  80. data/ext/rugged/vendor/libgit2-dist/src/commit.h +1 -1
  81. data/ext/rugged/vendor/libgit2-dist/src/common.h +12 -5
  82. data/ext/rugged/vendor/libgit2-dist/src/{win32 → compat}/fnmatch.c +1 -1
  83. data/ext/rugged/vendor/libgit2-dist/src/{win32 → compat}/fnmatch.h +3 -3
  84. data/ext/rugged/vendor/libgit2-dist/src/config.c +247 -158
  85. data/ext/rugged/vendor/libgit2-dist/src/config.h +10 -1
  86. data/ext/rugged/vendor/libgit2-dist/src/config_cache.c +94 -0
  87. data/ext/rugged/vendor/libgit2-dist/src/config_file.c +606 -496
  88. data/ext/rugged/vendor/libgit2-dist/src/config_file.h +31 -0
  89. data/ext/rugged/vendor/libgit2-dist/src/crlf.c +228 -0
  90. data/ext/rugged/vendor/libgit2-dist/src/date.c +876 -0
  91. data/ext/rugged/vendor/libgit2-dist/src/delta-apply.c +15 -9
  92. data/ext/rugged/vendor/libgit2-dist/src/delta-apply.h +2 -2
  93. data/ext/rugged/vendor/libgit2-dist/src/diff.c +814 -0
  94. data/ext/rugged/vendor/libgit2-dist/src/diff.h +43 -0
  95. data/ext/rugged/vendor/libgit2-dist/src/diff_output.c +794 -0
  96. data/ext/rugged/vendor/libgit2-dist/src/errors.c +89 -74
  97. data/ext/rugged/vendor/libgit2-dist/src/fetch.c +94 -66
  98. data/ext/rugged/vendor/libgit2-dist/src/fetch.h +5 -4
  99. data/ext/rugged/vendor/libgit2-dist/src/filebuf.c +157 -100
  100. data/ext/rugged/vendor/libgit2-dist/src/filebuf.h +22 -8
  101. data/ext/rugged/vendor/libgit2-dist/src/fileops.c +330 -206
  102. data/ext/rugged/vendor/libgit2-dist/src/fileops.h +82 -51
  103. data/ext/rugged/vendor/libgit2-dist/src/filter.c +165 -0
  104. data/ext/rugged/vendor/libgit2-dist/src/filter.h +119 -0
  105. data/ext/rugged/vendor/libgit2-dist/src/global.c +4 -4
  106. data/ext/rugged/vendor/libgit2-dist/src/global.h +4 -1
  107. data/ext/rugged/vendor/libgit2-dist/src/hash.c +1 -1
  108. data/ext/rugged/vendor/libgit2-dist/src/hash.h +1 -1
  109. data/ext/rugged/vendor/libgit2-dist/src/ignore.c +203 -0
  110. data/ext/rugged/vendor/libgit2-dist/src/ignore.h +38 -0
  111. data/ext/rugged/vendor/libgit2-dist/src/index.c +220 -169
  112. data/ext/rugged/vendor/libgit2-dist/src/index.h +5 -1
  113. data/ext/rugged/vendor/libgit2-dist/src/indexer.c +601 -102
  114. data/ext/rugged/vendor/libgit2-dist/src/iterator.c +748 -0
  115. data/ext/rugged/vendor/libgit2-dist/src/iterator.h +151 -0
  116. data/ext/rugged/vendor/libgit2-dist/src/khash.h +608 -0
  117. data/ext/rugged/vendor/libgit2-dist/src/map.h +6 -1
  118. data/ext/rugged/vendor/libgit2-dist/src/message.c +61 -0
  119. data/ext/rugged/vendor/libgit2-dist/src/message.h +14 -0
  120. data/ext/rugged/vendor/libgit2-dist/src/mwindow.c +27 -29
  121. data/ext/rugged/vendor/libgit2-dist/src/mwindow.h +4 -4
  122. data/ext/rugged/vendor/libgit2-dist/src/netops.c +375 -56
  123. data/ext/rugged/vendor/libgit2-dist/src/netops.h +12 -9
  124. data/ext/rugged/vendor/libgit2-dist/src/notes.c +548 -0
  125. data/ext/rugged/vendor/libgit2-dist/src/notes.h +28 -0
  126. data/ext/rugged/vendor/libgit2-dist/src/object.c +59 -21
  127. data/ext/rugged/vendor/libgit2-dist/src/odb.c +212 -175
  128. data/ext/rugged/vendor/libgit2-dist/src/odb.h +39 -2
  129. data/ext/rugged/vendor/libgit2-dist/src/odb_loose.c +238 -241
  130. data/ext/rugged/vendor/libgit2-dist/src/odb_pack.c +94 -106
  131. data/ext/rugged/vendor/libgit2-dist/src/oid.c +59 -60
  132. data/ext/rugged/vendor/libgit2-dist/src/oidmap.h +42 -0
  133. data/ext/rugged/vendor/libgit2-dist/src/pack.c +198 -170
  134. data/ext/rugged/vendor/libgit2-dist/src/pack.h +16 -9
  135. data/ext/rugged/vendor/libgit2-dist/src/path.c +496 -106
  136. data/ext/rugged/vendor/libgit2-dist/src/path.h +214 -20
  137. data/ext/rugged/vendor/libgit2-dist/src/pkt.c +88 -159
  138. data/ext/rugged/vendor/libgit2-dist/src/pkt.h +9 -5
  139. data/ext/rugged/vendor/libgit2-dist/src/pool.c +294 -0
  140. data/ext/rugged/vendor/libgit2-dist/src/pool.h +125 -0
  141. data/ext/rugged/vendor/libgit2-dist/src/posix.c +38 -16
  142. data/ext/rugged/vendor/libgit2-dist/src/posix.h +20 -2
  143. data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.c +1 -1
  144. data/ext/rugged/vendor/libgit2-dist/src/ppc/sha1.h +1 -1
  145. data/ext/rugged/vendor/libgit2-dist/src/pqueue.c +7 -7
  146. data/ext/rugged/vendor/libgit2-dist/src/pqueue.h +1 -1
  147. data/ext/rugged/vendor/libgit2-dist/src/protocol.c +21 -13
  148. data/ext/rugged/vendor/libgit2-dist/src/protocol.h +1 -1
  149. data/ext/rugged/vendor/libgit2-dist/src/reflog.c +125 -103
  150. data/ext/rugged/vendor/libgit2-dist/src/reflog.h +1 -1
  151. data/ext/rugged/vendor/libgit2-dist/src/refs.c +713 -640
  152. data/ext/rugged/vendor/libgit2-dist/src/refs.h +27 -3
  153. data/ext/rugged/vendor/libgit2-dist/src/refspec.c +51 -17
  154. data/ext/rugged/vendor/libgit2-dist/src/refspec.h +13 -1
  155. data/ext/rugged/vendor/libgit2-dist/src/remote.c +307 -119
  156. data/ext/rugged/vendor/libgit2-dist/src/remote.h +3 -2
  157. data/ext/rugged/vendor/libgit2-dist/src/repository.c +593 -442
  158. data/ext/rugged/vendor/libgit2-dist/src/repository.h +80 -2
  159. data/ext/rugged/vendor/libgit2-dist/src/reset.c +103 -0
  160. data/ext/rugged/vendor/libgit2-dist/src/revparse.c +753 -0
  161. data/ext/rugged/vendor/libgit2-dist/src/revwalk.c +434 -158
  162. data/ext/rugged/vendor/libgit2-dist/src/sha1.c +3 -3
  163. data/ext/rugged/vendor/libgit2-dist/src/sha1.h +2 -2
  164. data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.c +3 -2
  165. data/ext/rugged/vendor/libgit2-dist/src/sha1_lookup.h +1 -1
  166. data/ext/rugged/vendor/libgit2-dist/src/signature.c +69 -80
  167. data/ext/rugged/vendor/libgit2-dist/src/signature.h +1 -1
  168. data/ext/rugged/vendor/libgit2-dist/src/status.c +184 -638
  169. data/ext/rugged/vendor/libgit2-dist/src/strmap.h +64 -0
  170. data/ext/rugged/vendor/libgit2-dist/src/submodule.c +387 -0
  171. data/ext/rugged/vendor/libgit2-dist/src/tag.c +162 -137
  172. data/ext/rugged/vendor/libgit2-dist/src/tag.h +2 -1
  173. data/ext/rugged/vendor/libgit2-dist/src/thread-utils.c +1 -1
  174. data/ext/rugged/vendor/libgit2-dist/src/thread-utils.h +8 -8
  175. data/ext/rugged/vendor/libgit2-dist/src/transport.c +31 -19
  176. data/ext/rugged/vendor/libgit2-dist/src/transport.h +31 -11
  177. data/ext/rugged/vendor/libgit2-dist/src/transports/git.c +168 -193
  178. data/ext/rugged/vendor/libgit2-dist/src/transports/http.c +192 -241
  179. data/ext/rugged/vendor/libgit2-dist/src/transports/local.c +92 -86
  180. data/ext/rugged/vendor/libgit2-dist/src/tree-cache.c +32 -49
  181. data/ext/rugged/vendor/libgit2-dist/src/tree-cache.h +1 -1
  182. data/ext/rugged/vendor/libgit2-dist/src/tree.c +172 -145
  183. data/ext/rugged/vendor/libgit2-dist/src/tree.h +16 -2
  184. data/ext/rugged/vendor/libgit2-dist/src/tsort.c +16 -14
  185. data/ext/rugged/vendor/libgit2-dist/src/unix/map.c +8 -24
  186. data/ext/rugged/vendor/libgit2-dist/src/unix/posix.h +9 -3
  187. data/ext/rugged/vendor/libgit2-dist/src/util.c +94 -38
  188. data/ext/rugged/vendor/libgit2-dist/src/util.h +119 -13
  189. data/ext/rugged/vendor/libgit2-dist/src/vector.c +84 -31
  190. data/ext/rugged/vendor/libgit2-dist/src/vector.h +37 -4
  191. data/ext/rugged/vendor/libgit2-dist/src/win32/dir.c +81 -41
  192. data/ext/rugged/vendor/libgit2-dist/src/{dir.h → win32/dir.h} +4 -9
  193. data/ext/rugged/vendor/libgit2-dist/src/win32/map.c +19 -35
  194. data/ext/rugged/vendor/libgit2-dist/src/win32/mingw-compat.h +1 -1
  195. data/ext/rugged/vendor/libgit2-dist/src/win32/msvc-compat.h +5 -1
  196. data/ext/rugged/vendor/libgit2-dist/src/win32/posix.h +10 -8
  197. data/ext/rugged/vendor/libgit2-dist/src/win32/posix_w32.c +262 -118
  198. data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.c +12 -9
  199. data/ext/rugged/vendor/libgit2-dist/src/win32/pthread.h +1 -1
  200. data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.c +30 -26
  201. data/ext/rugged/vendor/libgit2-dist/src/win32/utf-conv.h +2 -1
  202. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xdiff.h +135 -0
  203. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xdiffi.c +572 -0
  204. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xdiffi.h +63 -0
  205. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xemit.c +253 -0
  206. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xemit.h +36 -0
  207. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xhistogram.c +371 -0
  208. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xinclude.h +46 -0
  209. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xmacros.h +54 -0
  210. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xmerge.c +619 -0
  211. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xpatience.c +358 -0
  212. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xprepare.c +483 -0
  213. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xprepare.h +34 -0
  214. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xtypes.h +67 -0
  215. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xutils.c +419 -0
  216. data/ext/rugged/vendor/libgit2-dist/src/xdiff/xutils.h +49 -0
  217. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/attr_expect.h +43 -0
  218. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/file.c +226 -0
  219. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/flags.c +108 -0
  220. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/lookup.c +262 -0
  221. data/ext/rugged/vendor/libgit2-dist/tests-clar/attr/repo.c +273 -0
  222. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/buf/basic.c +5 -5
  223. data/ext/rugged/vendor/libgit2-dist/tests-clar/clar_helpers.c +181 -0
  224. data/ext/rugged/vendor/libgit2-dist/tests-clar/clar_libgit2.h +55 -0
  225. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/commit.c +44 -0
  226. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/parse.c +350 -0
  227. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/signature.c +65 -0
  228. data/ext/rugged/vendor/libgit2-dist/tests-clar/commit/write.c +140 -0
  229. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/add.c +3 -3
  230. data/ext/rugged/vendor/libgit2-dist/tests-clar/config/multivar.c +151 -0
  231. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/new.c +5 -5
  232. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/read.c +44 -32
  233. data/ext/rugged/vendor/libgit2-dist/tests-clar/config/stress.c +61 -0
  234. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/config/write.c +20 -5
  235. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/buffer.c +613 -0
  236. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/dirent.c +39 -26
  237. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/env.c +115 -0
  238. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/errors.c +60 -0
  239. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/filebuf.c +4 -18
  240. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/hex.c +22 -0
  241. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/oid.c +6 -6
  242. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/path.c +420 -0
  243. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/pool.c +85 -0
  244. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/rmdir.c +68 -0
  245. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/string.c +1 -1
  246. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/strmap.c +102 -0
  247. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/core/strtol.c +1 -1
  248. data/ext/rugged/vendor/libgit2-dist/tests-clar/core/vector.c +191 -0
  249. data/ext/rugged/vendor/libgit2-dist/tests-clar/date/date.c +15 -0
  250. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/blob.c +254 -0
  251. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/diff_helpers.c +104 -0
  252. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/diff_helpers.h +47 -0
  253. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/index.c +92 -0
  254. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/iterator.c +572 -0
  255. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/patch.c +99 -0
  256. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/tree.c +210 -0
  257. data/ext/rugged/vendor/libgit2-dist/tests-clar/diff/workdir.c +543 -0
  258. data/ext/rugged/vendor/libgit2-dist/tests-clar/index/read_tree.c +46 -0
  259. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/index/rename.c +2 -12
  260. data/ext/rugged/vendor/libgit2-dist/tests-clar/index/tests.c +246 -0
  261. data/ext/rugged/vendor/libgit2-dist/tests-clar/network/createremotethenload.c +33 -0
  262. data/ext/rugged/vendor/libgit2-dist/tests-clar/network/remotelocal.c +137 -0
  263. data/ext/rugged/vendor/libgit2-dist/tests-clar/network/remotes.c +183 -0
  264. data/ext/rugged/vendor/libgit2-dist/tests-clar/notes/notes.c +133 -0
  265. data/ext/rugged/vendor/libgit2-dist/tests-clar/notes/notesref.c +57 -0
  266. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/blob/filter.c +125 -0
  267. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/blob/fromchunks.c +87 -0
  268. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/blob/write.c +69 -0
  269. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/commit/commitstagedfile.c +126 -0
  270. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/lookup.c +63 -0
  271. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/message.c +171 -0
  272. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/chars.c +3 -14
  273. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/compare.c +4 -4
  274. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/convert.c +10 -10
  275. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/data.h +0 -0
  276. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/fromstr.c +1 -1
  277. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/hash.c +21 -17
  278. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/short.c +1 -1
  279. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/size.c +1 -1
  280. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/raw/type2string.c +14 -14
  281. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/raw/write.c +455 -0
  282. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tag/peel.c +56 -0
  283. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tag/read.c +130 -0
  284. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tag/write.c +192 -0
  285. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/object/tree/frompath.c +22 -16
  286. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tree/read.c +75 -0
  287. data/ext/rugged/vendor/libgit2-dist/tests-clar/object/tree/write.c +84 -0
  288. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/loose.c +1 -1
  289. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/loose_data.h +0 -0
  290. data/ext/rugged/vendor/libgit2-dist/tests-clar/odb/mixed.c +24 -0
  291. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/pack_data.h +0 -0
  292. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/packed.c +1 -1
  293. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/odb/sorting.c +1 -1
  294. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/create.c +113 -0
  295. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/delete.c +91 -0
  296. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/listall.c +78 -0
  297. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/branches/move.c +72 -0
  298. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/crashes.c +17 -0
  299. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/create.c +149 -0
  300. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/delete.c +85 -0
  301. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/list.c +53 -0
  302. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/listall.c +36 -0
  303. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/lookup.c +42 -0
  304. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/normalize.c +200 -0
  305. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/overwrite.c +136 -0
  306. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/pack.c +67 -0
  307. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/read.c +194 -0
  308. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/reflog.c +123 -0
  309. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/rename.c +339 -0
  310. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/revparse.c +174 -0
  311. data/ext/rugged/vendor/libgit2-dist/tests-clar/refs/unicode.c +42 -0
  312. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/discover.c +142 -0
  313. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/repo/getters.c +19 -1
  314. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/init.c +235 -0
  315. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/open.c +282 -0
  316. data/ext/rugged/vendor/libgit2-dist/tests-clar/repo/setters.c +80 -0
  317. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/mixed.c +47 -0
  318. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/reset_helpers.c +10 -0
  319. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/reset_helpers.h +6 -0
  320. data/ext/rugged/vendor/libgit2-dist/tests-clar/reset/soft.c +102 -0
  321. data/ext/rugged/vendor/libgit2-dist/{tests/t05-revwalk.c → tests-clar/revwalk/basic.c} +85 -44
  322. data/ext/rugged/vendor/libgit2-dist/tests-clar/revwalk/mergebase.c +148 -0
  323. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/ignore.c +133 -0
  324. data/ext/rugged/vendor/libgit2-dist/{tests-clay → tests-clar}/status/single.c +2 -11
  325. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/status_data.h +202 -0
  326. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/status_helpers.c +49 -0
  327. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/status_helpers.h +33 -0
  328. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/submodules.c +112 -0
  329. data/ext/rugged/vendor/libgit2-dist/tests-clar/status/worktree.c +649 -0
  330. data/ext/rugged/vendor/libgit2-dist/tests-clar/threads/basic.c +20 -0
  331. data/ext/rugged/vendor/libgit2-dist.tar.gz +0 -0
  332. data/lib/rugged/commit.rb +35 -0
  333. data/lib/rugged/object.rb +7 -0
  334. data/lib/rugged/reference.rb +9 -0
  335. data/lib/rugged/repository.rb +99 -3
  336. data/lib/rugged/tag.rb +22 -0
  337. data/lib/rugged/tree.rb +8 -0
  338. data/lib/rugged/version.rb +1 -1
  339. data/lib/rugged.rb +4 -1
  340. data/test/blob_test.rb +2 -2
  341. data/test/commit_test.rb +27 -13
  342. data/test/config_test.rb +44 -0
  343. data/test/coverage/HEAD.json +1 -1
  344. data/test/fixtures/testrepo.git/config +2 -0
  345. data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
  346. data/test/lib_test.rb +7 -0
  347. data/test/object_test.rb +3 -3
  348. data/test/reference_test.rb +46 -8
  349. data/test/remote_test.rb +8 -2
  350. data/test/repo_pack_test.rb +3 -3
  351. data/test/repo_test.rb +79 -11
  352. data/test/tag_test.rb +9 -2
  353. data/test/test_helper.rb +21 -0
  354. data/test/tree_test.rb +18 -6
  355. metadata +205 -81
  356. data/ext/rugged/vendor/libgit2-dist/include/git2/zlib.h +0 -40
  357. data/ext/rugged/vendor/libgit2-dist/src/hashtable.c +0 -243
  358. data/ext/rugged/vendor/libgit2-dist/src/hashtable.h +0 -80
  359. data/ext/rugged/vendor/libgit2-dist/tests/t00-core.c +0 -628
  360. data/ext/rugged/vendor/libgit2-dist/tests/t01-data.h +0 -322
  361. data/ext/rugged/vendor/libgit2-dist/tests/t01-rawobj.c +0 -638
  362. data/ext/rugged/vendor/libgit2-dist/tests/t03-data.h +0 -344
  363. data/ext/rugged/vendor/libgit2-dist/tests/t03-objwrite.c +0 -255
  364. data/ext/rugged/vendor/libgit2-dist/tests/t04-commit.c +0 -788
  365. data/ext/rugged/vendor/libgit2-dist/tests/t06-index.c +0 -219
  366. data/ext/rugged/vendor/libgit2-dist/tests/t07-hashtable.c +0 -192
  367. data/ext/rugged/vendor/libgit2-dist/tests/t08-tag.c +0 -357
  368. data/ext/rugged/vendor/libgit2-dist/tests/t09-tree.c +0 -221
  369. data/ext/rugged/vendor/libgit2-dist/tests/t10-refs.c +0 -1294
  370. data/ext/rugged/vendor/libgit2-dist/tests/t12-repo.c +0 -174
  371. data/ext/rugged/vendor/libgit2-dist/tests/t13-threads.c +0 -41
  372. data/ext/rugged/vendor/libgit2-dist/tests/t17-bufs.c +0 -61
  373. data/ext/rugged/vendor/libgit2-dist/tests/t18-status.c +0 -448
  374. data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.c +0 -310
  375. data/ext/rugged/vendor/libgit2-dist/tests/test_helpers.h +0 -83
  376. data/ext/rugged/vendor/libgit2-dist/tests/test_lib.c +0 -198
  377. data/ext/rugged/vendor/libgit2-dist/tests/test_lib.h +0 -54
  378. data/ext/rugged/vendor/libgit2-dist/tests/test_main.c +0 -89
  379. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay.h +0 -187
  380. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_libgit2.h +0 -28
  381. data/ext/rugged/vendor/libgit2-dist/tests-clay/clay_main.c +0 -1073
  382. data/ext/rugged/vendor/libgit2-dist/tests-clay/config/stress.c +0 -39
  383. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/path.c +0 -139
  384. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/rmdir.c +0 -50
  385. data/ext/rugged/vendor/libgit2-dist/tests-clay/core/vector.c +0 -66
  386. data/ext/rugged/vendor/libgit2-dist/tests-clay/network/remotes.c +0 -50
  387. data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/init.c +0 -104
  388. data/ext/rugged/vendor/libgit2-dist/tests-clay/repo/open.c +0 -54
  389. data/ext/rugged/vendor/libgit2-dist/tests-clay/status/status_data.h +0 -48
  390. data/ext/rugged/vendor/libgit2-dist/tests-clay/status/worktree.c +0 -124
  391. data/lib/rugged/objects.rb +0 -45
  392. data/test/fixtures/testrepo.git/refs/heads/new_name +0 -1
@@ -1,10 +1,11 @@
1
1
  /*
2
- * Copyright (C) 2009-2011 the libgit2 contributors
2
+ * Copyright (C) 2009-2012 the libgit2 contributors
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
7
  #include <stdarg.h>
8
+ #include <ctype.h>
8
9
 
9
10
  #include "git2/object.h"
10
11
 
@@ -20,10 +21,11 @@
20
21
  #define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
21
22
  #define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
22
23
 
23
- #define GIT_FILE_CONTENT_PREFIX "gitdir: "
24
+ #define GIT_FILE_CONTENT_PREFIX "gitdir:"
24
25
 
25
26
  #define GIT_BRANCH_MASTER "master"
26
27
 
28
+ #define GIT_REPO_VERSION 0
27
29
 
28
30
  static void drop_odb(git_repository *repo)
29
31
  {
@@ -41,6 +43,8 @@ static void drop_config(git_repository *repo)
41
43
  git_config_free(repo->_config);
42
44
  repo->_config = NULL;
43
45
  }
46
+
47
+ git_repository__cvar_cache_clear(repo);
44
48
  }
45
49
 
46
50
  static void drop_index(git_repository *repo)
@@ -59,6 +63,8 @@ void git_repository_free(git_repository *repo)
59
63
 
60
64
  git_cache_free(&repo->objects);
61
65
  git_repository__refcache_free(&repo->references);
66
+ git_attr_cache_flush(repo);
67
+ git_submodule_config_free(repo);
62
68
 
63
69
  git__free(repo->path_repository);
64
70
  git__free(repo->workdir);
@@ -75,214 +81,424 @@ void git_repository_free(git_repository *repo)
75
81
  *
76
82
  * Open a repository object from its path
77
83
  */
78
- static int quickcheck_repository_dir(const char *repository_path)
84
+ static bool valid_repository_path(git_buf *repository_path)
79
85
  {
80
- char path_aux[GIT_PATH_MAX];
86
+ /* Check OBJECTS_DIR first, since it will generate the longest path name */
87
+ if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false)
88
+ return false;
81
89
 
82
90
  /* Ensure HEAD file exists */
83
- git_path_join(path_aux, repository_path, GIT_HEAD_FILE);
84
- if (git_futils_isfile(path_aux) < 0)
85
- return GIT_ERROR;
86
-
87
- git_path_join(path_aux, repository_path, GIT_OBJECTS_DIR);
88
- if (git_futils_isdir(path_aux) < 0)
89
- return GIT_ERROR;
91
+ if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
92
+ return false;
90
93
 
91
- git_path_join(path_aux, repository_path, GIT_REFS_DIR);
92
- if (git_futils_isdir(path_aux) < 0)
93
- return GIT_ERROR;
94
+ if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false)
95
+ return false;
94
96
 
95
- return GIT_SUCCESS;
97
+ return true;
96
98
  }
97
99
 
98
-
99
100
  static git_repository *repository_alloc(void)
100
101
  {
101
- int error;
102
-
103
102
  git_repository *repo = git__malloc(sizeof(git_repository));
104
103
  if (!repo)
105
104
  return NULL;
106
105
 
107
106
  memset(repo, 0x0, sizeof(git_repository));
108
107
 
109
- error = git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free);
110
- if (error < GIT_SUCCESS) {
108
+ if (git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free) < 0) {
111
109
  git__free(repo);
112
110
  return NULL;
113
111
  }
114
112
 
113
+ /* set all the entries in the cvar cache to `unset` */
114
+ git_repository__cvar_cache_clear(repo);
115
+
115
116
  return repo;
116
117
  }
117
118
 
118
119
  static int load_config_data(git_repository *repo)
119
120
  {
120
- int error, is_bare;
121
+ int is_bare;
121
122
  git_config *config;
122
123
 
123
- error = git_repository_config__weakptr(&config, repo);
124
- if (error < GIT_SUCCESS)
125
- return error;
124
+ if (git_repository_config__weakptr(&config, repo) < 0)
125
+ return -1;
126
126
 
127
- error = git_config_get_bool(config, "core.bare", &is_bare);
128
- if (error == GIT_SUCCESS)
127
+ /* Try to figure out if it's bare, default to non-bare if it's not set */
128
+ if (git_config_get_bool(&is_bare, config, "core.bare") < 0)
129
+ repo->is_bare = 0;
130
+ else
129
131
  repo->is_bare = is_bare;
130
132
 
131
- /* TODO: what else can we load/cache here? */
132
-
133
- return GIT_SUCCESS;
133
+ return 0;
134
134
  }
135
135
 
136
- static int load_workdir(git_repository *repo)
136
+ static int load_workdir(git_repository *repo, git_buf *parent_path)
137
137
  {
138
- if (!repo->is_bare) {
139
- char workdir_buf[GIT_PATH_MAX];
138
+ int error;
139
+ git_config *config;
140
+ const char *worktree;
141
+ git_buf worktree_buf = GIT_BUF_INIT;
140
142
 
141
- if (git_path_dirname_r(workdir_buf, sizeof(workdir_buf), repo->path_repository) < 0)
142
- return git__throw(GIT_EOSERR,
143
- "Failed to resolved working directory");
143
+ if (repo->is_bare)
144
+ return 0;
144
145
 
145
- git_path_join(workdir_buf, workdir_buf, "");
146
+ if (git_repository_config__weakptr(&config, repo) < 0)
147
+ return -1;
146
148
 
147
- repo->workdir = git__strdup(workdir_buf);
148
- if (repo->workdir == NULL)
149
- return GIT_ENOMEM;
149
+ error = git_config_get_string(&worktree, config, "core.worktree");
150
+ if (!error && worktree != NULL)
151
+ repo->workdir = git__strdup(worktree);
152
+ else if (error != GIT_ENOTFOUND)
153
+ return error;
154
+ else {
155
+ giterr_clear();
156
+
157
+ if (parent_path && git_path_isdir(parent_path->ptr))
158
+ repo->workdir = git_buf_detach(parent_path);
159
+ else {
160
+ git_path_dirname_r(&worktree_buf, repo->path_repository);
161
+ git_path_to_dir(&worktree_buf);
162
+ repo->workdir = git_buf_detach(&worktree_buf);
163
+ }
150
164
  }
151
165
 
152
- return GIT_SUCCESS;
166
+ GITERR_CHECK_ALLOC(repo->workdir);
167
+
168
+ return 0;
153
169
  }
154
170
 
155
- int git_repository_open(git_repository **repo_out, const char *path)
171
+ /*
172
+ * This function returns furthest offset into path where a ceiling dir
173
+ * is found, so we can stop processing the path at that point.
174
+ *
175
+ * Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
176
+ * the stack could remove directories name limits, but at the cost of doing
177
+ * repeated malloc/frees inside the loop below, so let's not do it now.
178
+ */
179
+ static int find_ceiling_dir_offset(
180
+ const char *path,
181
+ const char *ceiling_directories)
156
182
  {
157
- int error = GIT_SUCCESS;
158
- char path_buf[GIT_PATH_MAX];
159
- size_t path_len;
160
- git_repository *repo = NULL;
183
+ char buf[GIT_PATH_MAX + 1];
184
+ char buf2[GIT_PATH_MAX + 1];
185
+ const char *ceil, *sep;
186
+ size_t len, max_len = 0, min_len;
187
+
188
+ assert(path);
189
+
190
+ min_len = (size_t)(git_path_root(path) + 1);
191
+
192
+ if (ceiling_directories == NULL || min_len == 0)
193
+ return (int)min_len;
194
+
195
+ for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
196
+ for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
197
+ len = sep - ceil;
198
+
199
+ if (len == 0 || len >= sizeof(buf) || git_path_root(ceil) == -1)
200
+ continue;
161
201
 
162
- error = git_path_prettify_dir(path_buf, path, NULL);
163
- if (error < GIT_SUCCESS)
164
- return git__rethrow(error, "Failed to open repository");
202
+ strncpy(buf, ceil, len);
203
+ buf[len] = '\0';
204
+
205
+ if (p_realpath(buf, buf2) == NULL)
206
+ continue;
165
207
 
166
- path_len = strlen(path_buf);
208
+ len = strlen(buf2);
209
+ if (len > 0 && buf2[len-1] == '/')
210
+ buf[--len] = '\0';
167
211
 
168
- /**
169
- * Check if the path we've been given is actually the path
170
- * of the working dir, by testing if it contains a `.git`
171
- * folder inside of it.
172
- */
173
- git_path_join(path_buf, path_buf, DOT_GIT);
174
- if (git_futils_isdir(path_buf) < GIT_SUCCESS) {
175
- path_buf[path_len] = 0;
212
+ if (!strncmp(path, buf2, len) &&
213
+ path[len] == '/' &&
214
+ len > max_len)
215
+ {
216
+ max_len = len;
217
+ }
176
218
  }
177
219
 
178
- if (quickcheck_repository_dir(path_buf) < GIT_SUCCESS)
179
- return git__throw(GIT_ENOTAREPO,
180
- "The given path is not a valid Git repository");
220
+ return (int)(max_len <= min_len ? min_len : max_len);
221
+ }
181
222
 
182
- repo = repository_alloc();
183
- if (repo == NULL)
184
- return GIT_ENOMEM;
223
+ /*
224
+ * Read the contents of `file_path` and set `path_out` to the repo dir that
225
+ * it points to. Before calling, set `path_out` to the base directory that
226
+ * should be used if the contents of `file_path` are a relative path.
227
+ */
228
+ static int read_gitfile(git_buf *path_out, const char *file_path)
229
+ {
230
+ int error = 0;
231
+ git_buf file = GIT_BUF_INIT;
232
+ size_t prefix_len = strlen(GIT_FILE_CONTENT_PREFIX);
185
233
 
186
- repo->path_repository = git__strdup(path_buf);
187
- if (repo->path_repository == NULL) {
188
- git_repository_free(repo);
189
- return GIT_ENOMEM;
234
+ assert(path_out && file_path);
235
+
236
+ if (git_futils_readbuffer(&file, file_path) < 0)
237
+ return -1;
238
+
239
+ git_buf_rtrim(&file);
240
+
241
+ if (file.size <= prefix_len ||
242
+ memcmp(file.ptr, GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
243
+ {
244
+ giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path);
245
+ error = -1;
246
+ }
247
+ else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
248
+ const char *gitlink = ((const char *)file.ptr) + prefix_len;
249
+ while (*gitlink && git__isspace(*gitlink)) gitlink++;
250
+ error = git_path_prettify_dir(path_out, gitlink, path_out->ptr);
190
251
  }
191
252
 
192
- error = load_config_data(repo);
193
- if (error < GIT_SUCCESS) {
194
- git_repository_free(repo);
253
+ git_buf_free(&file);
254
+ return error;
255
+ }
256
+
257
+ static int find_repo(
258
+ git_buf *repo_path,
259
+ git_buf *parent_path,
260
+ const char *start_path,
261
+ uint32_t flags,
262
+ const char *ceiling_dirs)
263
+ {
264
+ int error;
265
+ git_buf path = GIT_BUF_INIT;
266
+ struct stat st;
267
+ dev_t initial_device = 0;
268
+ bool try_with_dot_git = false;
269
+ int ceiling_offset;
270
+
271
+ git_buf_free(repo_path);
272
+
273
+ if ((error = git_path_prettify_dir(&path, start_path, NULL)) < 0)
195
274
  return error;
275
+
276
+ ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
277
+
278
+ if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
279
+ return error;
280
+
281
+ while (!error && !git_buf_len(repo_path)) {
282
+ if (p_stat(path.ptr, &st) == 0) {
283
+ /* check that we have not crossed device boundaries */
284
+ if (initial_device == 0)
285
+ initial_device = st.st_dev;
286
+ else if (st.st_dev != initial_device &&
287
+ (flags & GIT_REPOSITORY_OPEN_CROSS_FS) == 0)
288
+ break;
289
+
290
+ if (S_ISDIR(st.st_mode)) {
291
+ if (valid_repository_path(&path)) {
292
+ git_path_to_dir(&path);
293
+ git_buf_set(repo_path, path.ptr, path.size);
294
+ break;
295
+ }
296
+ }
297
+ else if (S_ISREG(st.st_mode)) {
298
+ git_buf repo_link = GIT_BUF_INIT;
299
+
300
+ if (!(error = read_gitfile(&repo_link, path.ptr))) {
301
+ if (valid_repository_path(&repo_link))
302
+ git_buf_swap(repo_path, &repo_link);
303
+
304
+ git_buf_free(&repo_link);
305
+ break;
306
+ }
307
+ git_buf_free(&repo_link);
308
+ }
309
+ }
310
+
311
+ /* move up one directory level */
312
+ if (git_path_dirname_r(&path, path.ptr) < 0) {
313
+ error = -1;
314
+ break;
315
+ }
316
+
317
+ if (try_with_dot_git) {
318
+ /* if we tried original dir with and without .git AND either hit
319
+ * directory ceiling or NO_SEARCH was requested, then be done.
320
+ */
321
+ if (path.ptr[ceiling_offset] == '\0' ||
322
+ (flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0)
323
+ break;
324
+ /* otherwise look first for .git item */
325
+ error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
326
+ }
327
+ try_with_dot_git = !try_with_dot_git;
196
328
  }
197
329
 
198
- error = load_workdir(repo);
199
- if (error < GIT_SUCCESS) {
330
+ if (!error && parent_path != NULL) {
331
+ if (!git_buf_len(repo_path))
332
+ git_buf_clear(parent_path);
333
+ else {
334
+ git_path_dirname_r(parent_path, path.ptr);
335
+ git_path_to_dir(parent_path);
336
+ }
337
+ if (git_buf_oom(parent_path))
338
+ return -1;
339
+ }
340
+
341
+ git_buf_free(&path);
342
+
343
+ if (!git_buf_len(repo_path) && !error) {
344
+ giterr_set(GITERR_REPOSITORY,
345
+ "Could not find repository from '%s'", start_path);
346
+ error = GIT_ENOTFOUND;
347
+ }
348
+
349
+ return error;
350
+ }
351
+
352
+ int git_repository_open_ext(
353
+ git_repository **repo_ptr,
354
+ const char *start_path,
355
+ uint32_t flags,
356
+ const char *ceiling_dirs)
357
+ {
358
+ int error;
359
+ git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT;
360
+ git_repository *repo;
361
+
362
+ *repo_ptr = NULL;
363
+
364
+ if ((error = find_repo(&path, &parent, start_path, flags, ceiling_dirs)) < 0)
365
+ return error;
366
+
367
+ repo = repository_alloc();
368
+ GITERR_CHECK_ALLOC(repo);
369
+
370
+ repo->path_repository = git_buf_detach(&path);
371
+ GITERR_CHECK_ALLOC(repo->path_repository);
372
+
373
+ if ((error = load_config_data(repo)) < 0 ||
374
+ (error = load_workdir(repo, &parent)) < 0)
375
+ {
200
376
  git_repository_free(repo);
201
377
  return error;
202
378
  }
203
379
 
204
- *repo_out = repo;
205
- return GIT_SUCCESS;
380
+ git_buf_free(&parent);
381
+ *repo_ptr = repo;
382
+ return 0;
206
383
  }
207
384
 
208
- static int load_config(
209
- git_config **out,
210
- git_repository *repo,
211
- const char *global_config_path,
212
- const char *system_config_path)
385
+ int git_repository_open(git_repository **repo_out, const char *path)
386
+ {
387
+ return git_repository_open_ext(
388
+ repo_out, path, GIT_REPOSITORY_OPEN_NO_SEARCH, NULL);
389
+ }
390
+
391
+ int git_repository_discover(
392
+ char *repository_path,
393
+ size_t size,
394
+ const char *start_path,
395
+ int across_fs,
396
+ const char *ceiling_dirs)
213
397
  {
214
- char config_path[GIT_PATH_MAX];
398
+ git_buf path = GIT_BUF_INIT;
399
+ uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
215
400
  int error;
401
+
402
+ assert(start_path && repository_path && size > 0);
403
+
404
+ *repository_path = '\0';
405
+
406
+ if ((error = find_repo(&path, NULL, start_path, flags, ceiling_dirs)) < 0)
407
+ return error != GIT_ENOTFOUND ? -1 : error;
408
+
409
+ if (size < (size_t)(path.size + 1)) {
410
+ giterr_set(GITERR_REPOSITORY,
411
+ "The given buffer is too long to store the discovered path");
412
+ git_buf_free(&path);
413
+ return -1;
414
+ }
415
+
416
+ /* success: we discovered a repository */
417
+ git_buf_copy_cstr(repository_path, size, &path);
418
+ git_buf_free(&path);
419
+ return 0;
420
+ }
421
+
422
+ static int load_config(
423
+ git_config **out,
424
+ git_repository *repo,
425
+ const char *global_config_path,
426
+ const char *system_config_path)
427
+ {
428
+ git_buf config_path = GIT_BUF_INIT;
216
429
  git_config *cfg = NULL;
217
430
 
218
431
  assert(repo && out);
219
432
 
220
- error = git_config_new(&cfg);
221
- if (error < GIT_SUCCESS)
222
- return error;
433
+ if (git_config_new(&cfg) < 0)
434
+ return -1;
223
435
 
224
- git_path_join(config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
225
- error = git_config_add_file_ondisk(cfg, config_path, 3);
226
- if (error < GIT_SUCCESS)
227
- goto cleanup;
436
+ if (git_buf_joinpath(
437
+ &config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO) < 0)
438
+ goto on_error;
439
+
440
+ if (git_config_add_file_ondisk(cfg, config_path.ptr, 3) < 0)
441
+ goto on_error;
442
+
443
+ git_buf_free(&config_path);
228
444
 
229
445
  if (global_config_path != NULL) {
230
- error = git_config_add_file_ondisk(cfg, global_config_path, 2);
231
- if (error < GIT_SUCCESS)
232
- goto cleanup;
446
+ if (git_config_add_file_ondisk(cfg, global_config_path, 2) < 0)
447
+ goto on_error;
233
448
  }
234
449
 
235
450
  if (system_config_path != NULL) {
236
- error = git_config_add_file_ondisk(cfg, system_config_path, 1);
237
- if (error < GIT_SUCCESS)
238
- goto cleanup;
451
+ if (git_config_add_file_ondisk(cfg, system_config_path, 1) < 0)
452
+ goto on_error;
239
453
  }
240
454
 
241
455
  *out = cfg;
242
- return GIT_SUCCESS;
456
+ return 0;
243
457
 
244
- cleanup:
458
+ on_error:
459
+ git_buf_free(&config_path);
245
460
  git_config_free(cfg);
246
461
  *out = NULL;
247
- return error;
462
+ return -1;
248
463
  }
249
464
 
250
465
  int git_repository_config__weakptr(git_config **out, git_repository *repo)
251
466
  {
252
467
  if (repo->_config == NULL) {
253
- int error;
254
-
255
- char buf_global[GIT_PATH_MAX], buf_system[GIT_PATH_MAX];
468
+ git_buf global_buf = GIT_BUF_INIT, system_buf = GIT_BUF_INIT;
469
+ int res;
256
470
 
257
471
  const char *global_config_path = NULL;
258
472
  const char *system_config_path = NULL;
259
473
 
260
- if (git_config_find_global(buf_global) == GIT_SUCCESS)
261
- global_config_path = buf_global;
474
+ if (git_config_find_global_r(&global_buf) == 0)
475
+ global_config_path = global_buf.ptr;
476
+
477
+ if (git_config_find_system_r(&system_buf) == 0)
478
+ system_config_path = system_buf.ptr;
262
479
 
263
- if (git_config_find_system(buf_system) == GIT_SUCCESS)
264
- system_config_path = buf_system;
480
+ res = load_config(&repo->_config, repo, global_config_path, system_config_path);
265
481
 
266
- error = load_config(&repo->_config, repo, global_config_path, system_config_path);
267
- if (error < GIT_SUCCESS)
268
- return error;
482
+ git_buf_free(&global_buf);
483
+ git_buf_free(&system_buf);
484
+
485
+ if (res < 0)
486
+ return -1;
269
487
 
270
488
  GIT_REFCOUNT_OWN(repo->_config, repo);
271
489
  }
272
490
 
273
491
  *out = repo->_config;
274
- return GIT_SUCCESS;
492
+ return 0;
275
493
  }
276
494
 
277
495
  int git_repository_config(git_config **out, git_repository *repo)
278
496
  {
279
- int error = git_repository_config__weakptr(out, repo);
280
-
281
- if (error == GIT_SUCCESS) {
282
- GIT_REFCOUNT_INC(*out);
283
- }
497
+ if (git_repository_config__weakptr(out, repo) < 0)
498
+ return -1;
284
499
 
285
- return error;
500
+ GIT_REFCOUNT_INC(*out);
501
+ return 0;
286
502
  }
287
503
 
288
504
  void git_repository_set_config(git_repository *repo, git_config *config)
@@ -300,31 +516,32 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
300
516
  assert(repo && out);
301
517
 
302
518
  if (repo->_odb == NULL) {
303
- int error;
304
- char odb_path[GIT_PATH_MAX];
519
+ git_buf odb_path = GIT_BUF_INIT;
520
+ int res;
521
+
522
+ if (git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR) < 0)
523
+ return -1;
305
524
 
306
- git_path_join(odb_path, repo->path_repository, GIT_OBJECTS_DIR);
525
+ res = git_odb_open(&repo->_odb, odb_path.ptr);
526
+ git_buf_free(&odb_path); /* done with path */
307
527
 
308
- error = git_odb_open(&repo->_odb, odb_path);
309
- if (error < GIT_SUCCESS)
310
- return error;
528
+ if (res < 0)
529
+ return -1;
311
530
 
312
531
  GIT_REFCOUNT_OWN(repo->_odb, repo);
313
532
  }
314
533
 
315
534
  *out = repo->_odb;
316
- return GIT_SUCCESS;
535
+ return 0;
317
536
  }
318
537
 
319
538
  int git_repository_odb(git_odb **out, git_repository *repo)
320
539
  {
321
- int error = git_repository_odb__weakptr(out, repo);
322
-
323
- if (error == GIT_SUCCESS) {
324
- GIT_REFCOUNT_INC(*out);
325
- }
540
+ if (git_repository_odb__weakptr(out, repo) < 0)
541
+ return -1;
326
542
 
327
- return error;
543
+ GIT_REFCOUNT_INC(*out);
544
+ return 0;
328
545
  }
329
546
 
330
547
  void git_repository_set_odb(git_repository *repo, git_odb *odb)
@@ -335,41 +552,40 @@ void git_repository_set_odb(git_repository *repo, git_odb *odb)
335
552
 
336
553
  repo->_odb = odb;
337
554
  GIT_REFCOUNT_OWN(repo->_odb, repo);
555
+ GIT_REFCOUNT_INC(odb);
338
556
  }
339
557
 
340
558
  int git_repository_index__weakptr(git_index **out, git_repository *repo)
341
559
  {
342
560
  assert(out && repo);
343
561
 
344
- if (repo->is_bare)
345
- return git__throw(GIT_EBAREINDEX, "Cannot open index in bare repository");
346
-
347
562
  if (repo->_index == NULL) {
348
- int error;
349
- char index_path[GIT_PATH_MAX];
563
+ int res;
564
+ git_buf index_path = GIT_BUF_INIT;
565
+
566
+ if (git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE) < 0)
567
+ return -1;
350
568
 
351
- git_path_join(index_path, repo->path_repository, GIT_INDEX_FILE);
569
+ res = git_index_open(&repo->_index, index_path.ptr);
570
+ git_buf_free(&index_path); /* done with path */
352
571
 
353
- error = git_index_open(&repo->_index, index_path);
354
- if (error < GIT_SUCCESS)
355
- return error;
572
+ if (res < 0)
573
+ return -1;
356
574
 
357
575
  GIT_REFCOUNT_OWN(repo->_index, repo);
358
576
  }
359
577
 
360
578
  *out = repo->_index;
361
- return GIT_SUCCESS;
579
+ return 0;
362
580
  }
363
581
 
364
582
  int git_repository_index(git_index **out, git_repository *repo)
365
583
  {
366
- int error = git_repository_index__weakptr(out, repo);
584
+ if (git_repository_index__weakptr(out, repo) < 0)
585
+ return -1;
367
586
 
368
- if (error == GIT_SUCCESS) {
369
- GIT_REFCOUNT_INC(*out);
370
- }
371
-
372
- return error;
587
+ GIT_REFCOUNT_INC(*out);
588
+ return 0;
373
589
  }
374
590
 
375
591
  void git_repository_set_index(git_repository *repo, git_index *index)
@@ -380,409 +596,317 @@ void git_repository_set_index(git_repository *repo, git_index *index)
380
596
 
381
597
  repo->_index = index;
382
598
  GIT_REFCOUNT_OWN(repo->_index, repo);
599
+ GIT_REFCOUNT_INC(index);
383
600
  }
384
601
 
385
-
386
- static int retrieve_device(dev_t *device_out, const char *path)
602
+ static int check_repositoryformatversion(git_repository *repo)
387
603
  {
388
- struct stat path_info;
604
+ git_config *config;
605
+ int version;
389
606
 
390
- assert(device_out);
607
+ if (git_repository_config__weakptr(&config, repo) < 0)
608
+ return -1;
391
609
 
392
- if (p_lstat(path, &path_info))
393
- return git__throw(GIT_EOSERR, "Failed to get file informations: %s", path);
610
+ if (git_config_get_int32(&version, config, "core.repositoryformatversion") < 0)
611
+ return -1;
394
612
 
395
- *device_out = path_info.st_dev;
613
+ if (GIT_REPO_VERSION < version) {
614
+ giterr_set(GITERR_REPOSITORY,
615
+ "Unsupported repository version %d. Only versions up to %d are supported.",
616
+ version, GIT_REPO_VERSION);
617
+ return -1;
618
+ }
396
619
 
397
- return GIT_SUCCESS;
620
+ return 0;
398
621
  }
399
622
 
400
- static int retrieve_ceiling_directories_offset(const char *path, const char *ceiling_directories)
623
+ static int repo_init_reinit(git_repository **repo_out, const char *repository_path, int is_bare)
401
624
  {
402
- char buf[GIT_PATH_MAX + 1];
403
- char buf2[GIT_PATH_MAX + 1];
404
- const char *ceil, *sep;
405
- int len, max_len = -1;
406
- int min_len;
407
-
408
- assert(path);
625
+ git_repository *repo = NULL;
409
626
 
410
- min_len = git_path_root(path) + 1;
627
+ GIT_UNUSED(is_bare);
411
628
 
412
- if (ceiling_directories == NULL || min_len == 0)
413
- return min_len;
629
+ if (git_repository_open(&repo, repository_path) < 0)
630
+ return -1;
414
631
 
415
- for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
416
- for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
417
- len = sep - ceil;
418
-
419
- if (len == 0 || len > GIT_PATH_MAX || git_path_root(ceil) == -1)
420
- continue;
632
+ if (check_repositoryformatversion(repo) < 0) {
633
+ git_repository_free(repo);
634
+ return -1;
635
+ }
421
636
 
422
- strncpy(buf, ceil, len);
423
- buf[len] = '\0';
637
+ /* TODO: reinitialize the templates */
424
638
 
425
- if (p_realpath(buf, buf2) == NULL)
426
- continue;
639
+ *repo_out = repo;
640
+ return 0;
641
+ }
427
642
 
428
- len = strlen(buf2);
429
- if (len > 0 && buf2[len-1] == '/')
430
- buf[--len] = '\0';
643
+ static int repo_init_createhead(const char *git_dir)
644
+ {
645
+ git_buf ref_path = GIT_BUF_INIT;
646
+ git_filebuf ref = GIT_FILEBUF_INIT;
431
647
 
432
- if (!strncmp(path, buf2, len) &&
433
- path[len] == '/' &&
434
- len > max_len)
435
- {
436
- max_len = len;
437
- }
438
- }
648
+ if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
649
+ git_filebuf_open(&ref, ref_path.ptr, 0) < 0 ||
650
+ git_filebuf_printf(&ref, "ref: refs/heads/master\n") < 0 ||
651
+ git_filebuf_commit(&ref, GIT_REFS_FILE_MODE) < 0)
652
+ return -1;
439
653
 
440
- return max_len <= min_len ? min_len : max_len;
654
+ git_buf_free(&ref_path);
655
+ return 0;
441
656
  }
442
657
 
443
- static int read_gitfile(char *path_out, const char *file_path, const char *base_path)
658
+ static bool is_chmod_supported(const char *file_path)
444
659
  {
445
- git_fbuffer file;
446
- int error;
447
- size_t end_offset;
448
- char *data;
660
+ struct stat st1, st2;
661
+ static int _is_supported = -1;
449
662
 
450
- assert(path_out && file_path && base_path);
663
+ if (_is_supported > -1)
664
+ return _is_supported;
451
665
 
452
- error = git_futils_readbuffer(&file, file_path);
453
-
454
- if (error < GIT_SUCCESS)
455
- return error;
666
+ if (p_stat(file_path, &st1) < 0)
667
+ return false;
456
668
 
457
- data = (char*)(file.data);
669
+ if (p_chmod(file_path, st1.st_mode ^ S_IXUSR) < 0)
670
+ return false;
458
671
 
459
- if (git__prefixcmp(data, GIT_FILE_CONTENT_PREFIX)) {
460
- git_futils_freebuffer(&file);
461
- return git__throw(GIT_ENOTFOUND, "Invalid gitfile format `%s`", file_path);
462
- }
672
+ if (p_stat(file_path, &st2) < 0)
673
+ return false;
463
674
 
464
- end_offset = strlen(data) - 1;
675
+ _is_supported = (st1.st_mode != st2.st_mode);
676
+ return _is_supported;
677
+ }
465
678
 
466
- for (;data[end_offset] == '\r' || data[end_offset] == '\n'; --end_offset);
467
- data[end_offset + 1] = '\0';
679
+ static bool is_filesystem_case_insensitive(const char *gitdir_path)
680
+ {
681
+ git_buf path = GIT_BUF_INIT;
682
+ static int _is_insensitive = -1;
468
683
 
469
- if (strlen(GIT_FILE_CONTENT_PREFIX) == end_offset + 1) {
470
- git_futils_freebuffer(&file);
471
- return git__throw(GIT_ENOTFOUND, "No path in git file `%s`", file_path);
472
- }
684
+ if (_is_insensitive > -1)
685
+ return _is_insensitive;
473
686
 
474
- data = data + strlen(GIT_FILE_CONTENT_PREFIX);
475
- error = git_path_prettify_dir(path_out, data, base_path);
476
- git_futils_freebuffer(&file);
687
+ if (git_buf_joinpath(&path, gitdir_path, "CoNfIg") < 0)
688
+ goto cleanup;
477
689
 
478
- if (error == 0 && git_futils_exists(path_out) == 0)
479
- return GIT_SUCCESS;
690
+ _is_insensitive = git_path_exists(git_buf_cstr(&path));
480
691
 
481
- return git__throw(GIT_EOBJCORRUPTED, "The `.git` file points to an inexisting path");
692
+ cleanup:
693
+ git_buf_free(&path);
694
+ return _is_insensitive;
482
695
  }
483
696
 
484
- int git_repository_discover(
485
- char *repository_path,
486
- size_t size,
487
- const char *start_path,
488
- int across_fs,
489
- const char *ceiling_dirs)
697
+ static int repo_init_config(const char *git_dir, bool is_bare, bool is_reinit)
490
698
  {
491
- int error, ceiling_offset;
492
- char bare_path[GIT_PATH_MAX];
493
- char normal_path[GIT_PATH_MAX];
494
- char *found_path;
495
- dev_t current_device = 0;
699
+ git_buf cfg_path = GIT_BUF_INIT;
700
+ git_config *config = NULL;
496
701
 
497
- assert(start_path && repository_path);
702
+ #define SET_REPO_CONFIG(type, name, val) {\
703
+ if (git_config_set_##type(config, name, val) < 0) { \
704
+ git_buf_free(&cfg_path); \
705
+ git_config_free(config); \
706
+ return -1; } \
707
+ }
498
708
 
499
- error = git_path_prettify_dir(bare_path, start_path, NULL);
500
- if (error < GIT_SUCCESS)
501
- return error;
709
+ if (git_buf_joinpath(&cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
710
+ return -1;
502
711
 
503
- if (!across_fs) {
504
- error = retrieve_device(&current_device, bare_path);
505
- if (error < GIT_SUCCESS)
506
- return error;
712
+ if (git_config_open_ondisk(&config, git_buf_cstr(&cfg_path)) < 0) {
713
+ git_buf_free(&cfg_path);
714
+ return -1;
507
715
  }
508
716
 
509
- ceiling_offset = retrieve_ceiling_directories_offset(bare_path, ceiling_dirs);
510
- git_path_join(normal_path, bare_path, DOT_GIT);
511
-
512
- while(1) {
513
- /**
514
- * If the `.git` file is regular instead of
515
- * a directory, it should contain the path of the actual git repository
516
- */
517
- if (git_futils_isfile(normal_path) == GIT_SUCCESS) {
518
- error = read_gitfile(repository_path, normal_path, bare_path);
519
-
520
- if (error < GIT_SUCCESS)
521
- return git__rethrow(error,
522
- "Unable to read git file `%s`", normal_path);
523
-
524
- error = quickcheck_repository_dir(repository_path);
525
- if (error < GIT_SUCCESS)
526
- return git__throw(GIT_ENOTFOUND,
527
- "The `.git` file found at '%s' points"
528
- "to an inexisting Git folder", normal_path);
529
-
530
- return GIT_SUCCESS;
531
- }
532
-
533
- /**
534
- * If the `.git` file is a folder, we check inside of it
535
- */
536
- if (git_futils_isdir(normal_path) == GIT_SUCCESS) {
537
- error = quickcheck_repository_dir(normal_path);
538
- if (error == GIT_SUCCESS) {
539
- found_path = normal_path;
540
- break;
541
- }
542
- }
543
-
544
- /**
545
- * Otherwise, the repository may be bare, let's check
546
- * the root anyway
547
- */
548
- error = quickcheck_repository_dir(bare_path);
549
- if (error == GIT_SUCCESS) {
550
- found_path = bare_path;
551
- break;
552
- }
553
-
554
- if (git_path_dirname_r(normal_path, sizeof(normal_path), bare_path) < GIT_SUCCESS)
555
- return git__throw(GIT_EOSERR, "Failed to dirname '%s'", bare_path);
556
-
557
- if (!across_fs) {
558
- dev_t new_device;
559
- error = retrieve_device(&new_device, normal_path);
717
+ SET_REPO_CONFIG(bool, "core.bare", is_bare);
718
+ SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
719
+ SET_REPO_CONFIG(bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path)));
720
+
721
+ if (!is_reinit && is_filesystem_case_insensitive(git_dir))
722
+ SET_REPO_CONFIG(bool, "core.ignorecase", true);
723
+ /* TODO: what other defaults? */
560
724
 
561
- if (error < GIT_SUCCESS || current_device != new_device) {
562
- return git__throw(GIT_ENOTAREPO,
563
- "Not a git repository (or any parent up to mount parent %s)\n"
564
- "Stopping at filesystem boundary.", bare_path);
565
- }
566
- current_device = new_device;
567
- }
725
+ git_buf_free(&cfg_path);
726
+ git_config_free(config);
727
+ return 0;
728
+ }
568
729
 
569
- strcpy(bare_path, normal_path);
570
- git_path_join(normal_path, bare_path, DOT_GIT);
730
+ #define GIT_HOOKS_DIR "hooks/"
731
+ #define GIT_HOOKS_DIR_MODE 0755
571
732
 
572
- // nothing has been found, lets try the parent directory
573
- if (bare_path[ceiling_offset] == '\0') {
574
- return git__throw(GIT_ENOTAREPO,
575
- "Not a git repository (or any of the parent directories): %s", start_path);
576
- }
577
- }
733
+ #define GIT_HOOKS_README_FILE GIT_HOOKS_DIR "README.sample"
734
+ #define GIT_HOOKS_README_MODE 0755
735
+ #define GIT_HOOKS_README_CONTENT \
736
+ "#!/bin/sh\n"\
737
+ "#\n"\
738
+ "# Place appropriately named executable hook scripts into this directory\n"\
739
+ "# to intercept various actions that git takes. See `git help hooks` for\n"\
740
+ "# more information.\n"
578
741
 
579
- if (size < strlen(found_path) + 2) {
580
- return git__throw(GIT_ESHORTBUFFER,
581
- "The repository buffer is not long enough to handle the repository path `%s`", found_path);
582
- }
742
+ #define GIT_INFO_DIR "info/"
743
+ #define GIT_INFO_DIR_MODE 0755
583
744
 
584
- git_path_join(repository_path, found_path, "");
585
- return GIT_SUCCESS;
586
- }
745
+ #define GIT_INFO_EXCLUDE_FILE GIT_INFO_DIR "exclude"
746
+ #define GIT_INFO_EXCLUDE_MODE 0644
747
+ #define GIT_INFO_EXCLUDE_CONTENT \
748
+ "# File patterns to ignore; see `git help ignore` for more information.\n"\
749
+ "# Lines that start with '#' are comments.\n"
587
750
 
588
- static int repo_init_reinit(const char *repository_path, int is_bare)
589
- {
590
- /* TODO: reinit the repository */
591
- return git__throw(GIT_ENOTIMPLEMENTED,
592
- "Failed to reinitialize the %srepository at '%s'. "
593
- "This feature is not yet implemented",
594
- is_bare ? "bare " : "", repository_path);
595
- }
751
+ #define GIT_DESC_FILE "description"
752
+ #define GIT_DESC_MODE 0644
753
+ #define GIT_DESC_CONTENT "Unnamed repository; edit this file 'description' to name the repository.\n"
596
754
 
597
- static int repo_init_createhead(const char *git_dir)
755
+ static int repo_write_template(
756
+ const char *git_dir, const char *file, mode_t mode, const char *content)
598
757
  {
599
- char ref_path[GIT_PATH_MAX];
600
- git_filebuf ref = GIT_FILEBUF_INIT;
601
-
602
- git_path_join(ref_path, git_dir, GIT_HEAD_FILE);
758
+ git_buf path = GIT_BUF_INIT;
759
+ int fd, error = 0;
603
760
 
604
- git_filebuf_open(&ref, ref_path, 0);
605
- git_filebuf_printf(&ref, "ref: refs/heads/master\n");
761
+ if (git_buf_joinpath(&path, git_dir, file) < 0)
762
+ return -1;
606
763
 
607
- return git_filebuf_commit(&ref, GIT_REFS_FILE_MODE);
608
- }
764
+ fd = p_open(git_buf_cstr(&path), O_WRONLY | O_CREAT | O_EXCL, mode);
609
765
 
610
- static int repo_init_config(const char *git_dir, int is_bare)
611
- {
612
- char cfg_path[GIT_PATH_MAX];
613
- git_config *config;
614
- int error = GIT_SUCCESS;
766
+ if (fd >= 0) {
767
+ error = p_write(fd, content, strlen(content));
615
768
 
616
- #define SET_REPO_CONFIG(type, name, val) {\
617
- error = git_config_set_##type(config, name, val);\
618
- if (error < GIT_SUCCESS)\
619
- goto cleanup;\
620
- }
769
+ p_close(fd);
770
+ }
771
+ else if (errno != EEXIST)
772
+ error = fd;
621
773
 
622
- git_path_join(cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO);
774
+ git_buf_free(&path);
623
775
 
624
- error = git_config_open_ondisk(&config, cfg_path);
625
- if (error < GIT_SUCCESS)
626
- return error;
776
+ if (error)
777
+ giterr_set(GITERR_OS,
778
+ "Failed to initialize repository with template '%s'", file);
627
779
 
628
- SET_REPO_CONFIG(bool, "core.bare", is_bare);
629
- SET_REPO_CONFIG(int32, "core.repositoryformatversion", 0);
630
- /* TODO: what other defaults? */
631
-
632
- cleanup:
633
- git_config_free(config);
634
780
  return error;
635
781
  }
636
782
 
637
783
  static int repo_init_structure(const char *git_dir, int is_bare)
638
784
  {
639
- int error;
640
-
641
- char temp_path[GIT_PATH_MAX];
642
-
643
- if (git_futils_mkdir_r(git_dir, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE))
644
- return git__throw(GIT_ERROR, "Failed to initialize repository structure. Could not mkdir");
785
+ int i;
786
+ struct { const char *dir; mode_t mode; } dirs[] = {
787
+ { GIT_OBJECTS_INFO_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/info/' */
788
+ { GIT_OBJECTS_PACK_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/pack/' */
789
+ { GIT_REFS_HEADS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/heads/' */
790
+ { GIT_REFS_TAGS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/tags/' */
791
+ { GIT_HOOKS_DIR, GIT_HOOKS_DIR_MODE }, /* '/hooks/' */
792
+ { GIT_INFO_DIR, GIT_INFO_DIR_MODE }, /* '/info/' */
793
+ { NULL, 0 }
794
+ };
795
+ struct { const char *file; mode_t mode; const char *content; } tmpl[] = {
796
+ { GIT_DESC_FILE, GIT_DESC_MODE, GIT_DESC_CONTENT },
797
+ { GIT_HOOKS_README_FILE, GIT_HOOKS_README_MODE, GIT_HOOKS_README_CONTENT },
798
+ { GIT_INFO_EXCLUDE_FILE, GIT_INFO_EXCLUDE_MODE, GIT_INFO_EXCLUDE_CONTENT },
799
+ { NULL, 0, NULL }
800
+ };
801
+
802
+ /* Make the base directory */
803
+ if (git_futils_mkdir_r(git_dir, NULL, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE) < 0)
804
+ return -1;
645
805
 
646
806
  /* Hides the ".git" directory */
647
807
  if (!is_bare) {
648
808
  #ifdef GIT_WIN32
649
- error = p_hide_directory__w32(git_dir);
650
- if (error < GIT_SUCCESS)
651
- return git__rethrow(error, "Failed to initialize repository structure");
809
+ if (p_hide_directory__w32(git_dir) < 0) {
810
+ giterr_set(GITERR_REPOSITORY,
811
+ "Failed to mark Git repository folder as hidden");
812
+ return -1;
813
+ }
652
814
  #endif
653
815
  }
654
816
 
655
- /* Creates the '/objects/info/' directory */
656
- git_path_join(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
657
- error = git_futils_mkdir_r(temp_path, GIT_OBJECT_DIR_MODE);
658
- if (error < GIT_SUCCESS)
659
- return git__rethrow(error, "Failed to initialize repository structure");
660
-
661
- /* Creates the '/objects/pack/' directory */
662
- git_path_join(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
663
- error = p_mkdir(temp_path, GIT_OBJECT_DIR_MODE);
664
- if (error < GIT_SUCCESS)
665
- return git__throw(error, "Unable to create `%s` folder", temp_path);
666
-
667
- /* Creates the '/refs/heads/' directory */
668
- git_path_join(temp_path, git_dir, GIT_REFS_HEADS_DIR);
669
- error = git_futils_mkdir_r(temp_path, GIT_REFS_DIR_MODE);
670
- if (error < GIT_SUCCESS)
671
- return git__rethrow(error, "Failed to initialize repository structure");
672
-
673
- /* Creates the '/refs/tags/' directory */
674
- git_path_join(temp_path, git_dir, GIT_REFS_TAGS_DIR);
675
- error = p_mkdir(temp_path, GIT_REFS_DIR_MODE);
676
- if (error < GIT_SUCCESS)
677
- return git__throw(error, "Unable to create `%s` folder", temp_path);
817
+ /* Make subdirectories as needed */
818
+ for (i = 0; dirs[i].dir != NULL; ++i) {
819
+ if (git_futils_mkdir_r(dirs[i].dir, git_dir, dirs[i].mode) < 0)
820
+ return -1;
821
+ }
678
822
 
679
- /* TODO: what's left? templates? */
823
+ /* Make template files as needed */
824
+ for (i = 0; tmpl[i].file != NULL; ++i) {
825
+ if (repo_write_template(
826
+ git_dir, tmpl[i].file, tmpl[i].mode, tmpl[i].content) < 0)
827
+ return -1;
828
+ }
680
829
 
681
- return GIT_SUCCESS;
830
+ return 0;
682
831
  }
683
832
 
684
833
  int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare)
685
834
  {
686
- int error = GIT_SUCCESS;
687
- git_repository *repo = NULL;
688
- char repository_path[GIT_PATH_MAX];
835
+ git_buf repository_path = GIT_BUF_INIT;
836
+ bool is_reinit;
837
+ int result = -1;
689
838
 
690
839
  assert(repo_out && path);
691
840
 
692
- git_path_join(repository_path, path, is_bare ? "" : GIT_DIR);
841
+ if (git_buf_joinpath(&repository_path, path, is_bare ? "" : GIT_DIR) < 0)
842
+ goto cleanup;
693
843
 
694
- if (git_futils_isdir(repository_path)) {
695
- if (quickcheck_repository_dir(repository_path) == GIT_SUCCESS)
696
- return repo_init_reinit(repository_path, is_bare);
697
- }
844
+ is_reinit = git_path_isdir(repository_path.ptr) && valid_repository_path(&repository_path);
698
845
 
699
- error = repo_init_structure(repository_path, is_bare);
700
- if (error < GIT_SUCCESS)
701
- goto cleanup;
846
+ if (is_reinit) {
847
+ if (repo_init_reinit(repo_out, repository_path.ptr, is_bare) < 0)
848
+ goto cleanup;
702
849
 
703
- error = repo_init_config(repository_path, is_bare);
704
- if (error < GIT_SUCCESS)
705
- goto cleanup;
850
+ result = repo_init_config(repository_path.ptr, is_bare, is_reinit);
851
+ }
706
852
 
707
- error = repo_init_createhead(repository_path);
708
- if (error < GIT_SUCCESS)
853
+ if (repo_init_structure(repository_path.ptr, is_bare) < 0 ||
854
+ repo_init_config(repository_path.ptr, is_bare, is_reinit) < 0 ||
855
+ repo_init_createhead(repository_path.ptr) < 0 ||
856
+ git_repository_open(repo_out, repository_path.ptr) < 0) {
709
857
  goto cleanup;
858
+ }
710
859
 
711
- return git_repository_open(repo_out, repository_path);
860
+ result = 0;
712
861
 
713
862
  cleanup:
714
- git_repository_free(repo);
715
- return git__rethrow(error, "Failed to (re)init the repository `%s`", path);
863
+ git_buf_free(&repository_path);
864
+ return result;
716
865
  }
717
866
 
718
867
  int git_repository_head_detached(git_repository *repo)
719
868
  {
720
869
  git_reference *ref;
721
- int error;
722
- size_t _size;
723
- git_otype type;
724
870
  git_odb *odb = NULL;
871
+ int exists;
725
872
 
726
- error = git_repository_odb__weakptr(&odb, repo);
727
- if (error < GIT_SUCCESS)
728
- return error;
873
+ if (git_repository_odb__weakptr(&odb, repo) < 0)
874
+ return -1;
729
875
 
730
- error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
731
- if (error < GIT_SUCCESS)
732
- return error;
876
+ if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0)
877
+ return -1;
733
878
 
734
879
  if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
735
880
  git_reference_free(ref);
736
881
  return 0;
737
882
  }
738
883
 
739
- error = git_odb_read_header(&_size, &type, odb, git_reference_oid(ref));
884
+ exists = git_odb_exists(odb, git_reference_oid(ref));
740
885
 
741
886
  git_reference_free(ref);
742
-
743
- if (error < GIT_SUCCESS)
744
- return error;
745
-
746
- if (type != GIT_OBJ_COMMIT)
747
- return git__throw(GIT_EOBJCORRUPTED, "HEAD is not a commit");
748
-
749
- return 1;
887
+ return exists;
750
888
  }
751
889
 
752
890
  int git_repository_head(git_reference **head_out, git_repository *repo)
753
891
  {
754
- git_reference *ref, *resolved_ref;
755
- int error;
756
-
757
- *head_out = NULL;
758
-
759
- error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
760
- if (error < GIT_SUCCESS)
761
- return git__rethrow(GIT_ENOTAREPO, "Failed to locate the HEAD");
762
-
763
- error = git_reference_resolve(&resolved_ref, ref);
764
- if (error < GIT_SUCCESS) {
765
- git_reference_free(ref);
766
- return git__rethrow(error, "Failed to resolve the HEAD");
767
- }
768
-
769
- git_reference_free(ref);
770
-
771
- *head_out = resolved_ref;
772
- return GIT_SUCCESS;
892
+ return git_reference_lookup_resolved(head_out, repo, GIT_HEAD_FILE, -1);
773
893
  }
774
894
 
775
895
  int git_repository_head_orphan(git_repository *repo)
776
896
  {
777
- git_reference *ref;
897
+ git_reference *ref = NULL;
778
898
  int error;
779
899
 
780
900
  error = git_repository_head(&ref, repo);
901
+ git_reference_free(ref);
781
902
 
782
- if (error == GIT_SUCCESS)
783
- git_reference_free(ref);
903
+ if (error == GIT_ENOTFOUND)
904
+ return 1;
784
905
 
785
- return error == GIT_ENOTFOUND ? 1 : error;
906
+ if (error < 0)
907
+ return -1;
908
+
909
+ return 0;
786
910
  }
787
911
 
788
912
  int git_repository_is_empty(git_repository *repo)
@@ -790,9 +914,8 @@ int git_repository_is_empty(git_repository *repo)
790
914
  git_reference *head = NULL, *branch = NULL;
791
915
  int error;
792
916
 
793
- error = git_reference_lookup(&head, repo, "HEAD");
794
- if (error < GIT_SUCCESS)
795
- return git__throw(error, "Corrupted repository. HEAD does not exist");
917
+ if (git_reference_lookup(&head, repo, "HEAD") < 0)
918
+ return -1;
796
919
 
797
920
  if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
798
921
  git_reference_free(head);
@@ -809,7 +932,13 @@ int git_repository_is_empty(git_repository *repo)
809
932
  git_reference_free(head);
810
933
  git_reference_free(branch);
811
934
 
812
- return error == GIT_ENOTFOUND ? 1 : error;
935
+ if (error == GIT_ENOTFOUND)
936
+ return 1;
937
+
938
+ if (error < 0)
939
+ return -1;
940
+
941
+ return 0;
813
942
  }
814
943
 
815
944
  const char *git_repository_path(git_repository *repo)
@@ -830,16 +959,18 @@ const char *git_repository_workdir(git_repository *repo)
830
959
 
831
960
  int git_repository_set_workdir(git_repository *repo, const char *workdir)
832
961
  {
962
+ git_buf path = GIT_BUF_INIT;
963
+
833
964
  assert(repo && workdir);
834
965
 
835
- free(repo->workdir);
966
+ if (git_path_prettify_dir(&path, workdir, NULL) < 0)
967
+ return -1;
836
968
 
837
- repo->workdir = git__strdup(workdir);
838
- if (repo->workdir == NULL)
839
- return GIT_ENOMEM;
969
+ git__free(repo->workdir);
840
970
 
971
+ repo->workdir = git_buf_detach(&path);
841
972
  repo->is_bare = 0;
842
- return GIT_SUCCESS;
973
+ return 0;
843
974
  }
844
975
 
845
976
  int git_repository_is_bare(git_repository *repo)
@@ -847,3 +978,23 @@ int git_repository_is_bare(git_repository *repo)
847
978
  assert(repo);
848
979
  return repo->is_bare;
849
980
  }
981
+
982
+ int git_repository_head_tree(git_tree **tree, git_repository *repo)
983
+ {
984
+ git_oid head_oid;
985
+ git_object *obj = NULL;
986
+
987
+ if (git_reference_name_to_oid(&head_oid, repo, GIT_HEAD_FILE) < 0) {
988
+ /* cannot resolve HEAD - probably brand new repo */
989
+ giterr_clear();
990
+ *tree = NULL;
991
+ return 0;
992
+ }
993
+
994
+ if (git_object_lookup(&obj, repo, &head_oid, GIT_OBJ_ANY) < 0 ||
995
+ git_object__resolve_to_type(&obj, GIT_OBJ_TREE) < 0)
996
+ return -1;
997
+
998
+ *tree = (git_tree *)obj;
999
+ return 0;
1000
+ }