rugged 0.19.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (668) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -1
  3. data/README.md +184 -33
  4. data/ext/rugged/extconf.rb +111 -28
  5. data/ext/rugged/rugged.c +327 -89
  6. data/ext/rugged/rugged.h +64 -28
  7. data/ext/rugged/rugged_allocator.c +89 -0
  8. data/ext/rugged/rugged_backend.c +17 -0
  9. data/ext/rugged/rugged_blame.c +278 -0
  10. data/ext/rugged/rugged_blob.c +301 -75
  11. data/ext/rugged/rugged_branch.c +92 -242
  12. data/ext/rugged/rugged_branch_collection.c +388 -0
  13. data/ext/rugged/rugged_commit.c +575 -79
  14. data/ext/rugged/rugged_config.c +129 -36
  15. data/ext/rugged/rugged_cred.c +131 -0
  16. data/ext/rugged/rugged_diff.c +291 -122
  17. data/ext/rugged/rugged_diff_delta.c +16 -22
  18. data/ext/rugged/rugged_diff_hunk.c +35 -51
  19. data/ext/rugged/rugged_diff_line.c +23 -36
  20. data/ext/rugged/rugged_index.c +289 -152
  21. data/ext/rugged/rugged_note.c +50 -60
  22. data/ext/rugged/rugged_object.c +13 -30
  23. data/ext/rugged/rugged_patch.c +400 -0
  24. data/ext/rugged/rugged_rebase.c +397 -0
  25. data/ext/rugged/rugged_reference.c +76 -346
  26. data/ext/rugged/rugged_reference_collection.c +423 -0
  27. data/ext/rugged/rugged_remote.c +438 -461
  28. data/ext/rugged/rugged_remote_collection.c +435 -0
  29. data/ext/rugged/rugged_repo.c +1548 -365
  30. data/ext/rugged/rugged_revwalk.c +378 -99
  31. data/ext/rugged/rugged_settings.c +86 -23
  32. data/ext/rugged/rugged_signature.c +47 -37
  33. data/ext/rugged/rugged_submodule.c +835 -0
  34. data/ext/rugged/rugged_submodule_collection.c +366 -0
  35. data/ext/rugged/rugged_tag.c +88 -210
  36. data/ext/rugged/rugged_tag_collection.c +326 -0
  37. data/ext/rugged/rugged_tree.c +460 -217
  38. data/lib/rugged/attributes.rb +46 -0
  39. data/lib/rugged/blob.rb +33 -0
  40. data/lib/rugged/branch.rb +12 -16
  41. data/lib/rugged/commit.rb +9 -0
  42. data/lib/rugged/console.rb +5 -0
  43. data/lib/rugged/credentials.rb +48 -0
  44. data/lib/rugged/diff/delta.rb +6 -2
  45. data/lib/rugged/diff/hunk.rb +9 -9
  46. data/lib/rugged/diff/line.rb +28 -5
  47. data/lib/rugged/diff.rb +7 -1
  48. data/lib/rugged/index.rb +120 -0
  49. data/lib/rugged/object.rb +5 -0
  50. data/lib/rugged/patch.rb +41 -0
  51. data/lib/rugged/reference.rb +6 -3
  52. data/lib/rugged/remote.rb +5 -9
  53. data/lib/rugged/repository.rb +126 -14
  54. data/lib/rugged/submodule_collection.rb +53 -0
  55. data/lib/rugged/tag.rb +45 -16
  56. data/lib/rugged/tree.rb +163 -1
  57. data/lib/rugged/version.rb +6 -1
  58. data/lib/rugged/walker.rb +5 -0
  59. data/lib/rugged.rb +16 -1
  60. data/vendor/libgit2/AUTHORS +77 -0
  61. data/vendor/libgit2/CMakeLists.txt +317 -0
  62. data/vendor/libgit2/COPYING +993 -0
  63. data/vendor/libgit2/cmake/Modules/AddCFlagIfSupported.cmake +30 -0
  64. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.c.in +29 -0
  65. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.cmake +96 -0
  66. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +11 -0
  67. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +26 -0
  68. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +324 -0
  69. data/vendor/libgit2/cmake/Modules/FindHTTP_Parser.cmake +39 -0
  70. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +45 -0
  71. data/vendor/libgit2/cmake/Modules/FindPkgLibraries.cmake +28 -0
  72. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +28 -0
  73. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +20 -0
  74. data/vendor/libgit2/cmake/Modules/FindmbedTLS.cmake +93 -0
  75. data/vendor/libgit2/cmake/Modules/IdeSplitSources.cmake +22 -0
  76. data/vendor/libgit2/deps/http-parser/CMakeLists.txt +5 -0
  77. data/vendor/libgit2/deps/http-parser/COPYING +23 -0
  78. data/vendor/libgit2/deps/http-parser/http_parser.c +5 -2
  79. data/vendor/libgit2/deps/http-parser/http_parser.h +2 -0
  80. data/vendor/libgit2/deps/regex/CMakeLists.txt +2 -0
  81. data/vendor/libgit2/deps/regex/COPYING +502 -0
  82. data/vendor/libgit2/deps/regex/regex.c +10 -3
  83. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +26 -0
  84. data/vendor/libgit2/deps/winhttp/COPYING.GPL +993 -0
  85. data/vendor/libgit2/deps/winhttp/COPYING.LGPL +502 -0
  86. data/vendor/libgit2/deps/winhttp/urlmon.h +45 -0
  87. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -0
  88. data/vendor/libgit2/deps/winhttp/winhttp.h +594 -0
  89. data/vendor/libgit2/deps/winhttp/winhttp64.def +29 -0
  90. data/vendor/libgit2/deps/zlib/CMakeLists.txt +5 -0
  91. data/vendor/libgit2/deps/zlib/COPYING +27 -0
  92. data/vendor/libgit2/deps/zlib/adler32.c +51 -34
  93. data/vendor/libgit2/deps/zlib/crc32.c +61 -61
  94. data/vendor/libgit2/deps/zlib/crc32.h +1 -1
  95. data/vendor/libgit2/deps/zlib/deflate.c +681 -352
  96. data/vendor/libgit2/deps/zlib/deflate.h +25 -18
  97. data/vendor/libgit2/deps/zlib/gzguts.h +218 -0
  98. data/vendor/libgit2/deps/zlib/infback.c +640 -0
  99. data/vendor/libgit2/deps/zlib/inffast.c +36 -53
  100. data/vendor/libgit2/deps/zlib/inffixed.h +3 -3
  101. data/vendor/libgit2/deps/zlib/inflate.c +167 -86
  102. data/vendor/libgit2/deps/zlib/inflate.h +7 -4
  103. data/vendor/libgit2/deps/zlib/inftrees.c +24 -50
  104. data/vendor/libgit2/deps/zlib/trees.c +55 -96
  105. data/vendor/libgit2/deps/zlib/zconf.h +499 -19
  106. data/vendor/libgit2/deps/zlib/zlib.h +526 -227
  107. data/vendor/libgit2/deps/zlib/zutil.c +39 -32
  108. data/vendor/libgit2/deps/zlib/zutil.h +75 -78
  109. data/vendor/libgit2/include/git2/annotated_commit.h +125 -0
  110. data/vendor/libgit2/include/git2/apply.h +129 -0
  111. data/vendor/libgit2/include/git2/attr.h +36 -21
  112. data/vendor/libgit2/include/git2/blame.h +229 -0
  113. data/vendor/libgit2/include/git2/blob.h +81 -44
  114. data/vendor/libgit2/include/git2/branch.h +81 -42
  115. data/vendor/libgit2/include/git2/buffer.h +128 -0
  116. data/vendor/libgit2/include/git2/checkout.h +141 -67
  117. data/vendor/libgit2/include/git2/cherrypick.h +92 -0
  118. data/vendor/libgit2/include/git2/clone.h +157 -58
  119. data/vendor/libgit2/include/git2/commit.h +231 -12
  120. data/vendor/libgit2/include/git2/common.h +216 -30
  121. data/vendor/libgit2/include/git2/config.h +274 -48
  122. data/vendor/libgit2/include/git2/cred_helpers.h +4 -4
  123. data/vendor/libgit2/include/git2/deprecated.h +253 -0
  124. data/vendor/libgit2/include/git2/describe.h +189 -0
  125. data/vendor/libgit2/include/git2/diff.h +985 -575
  126. data/vendor/libgit2/include/git2/errors.h +93 -52
  127. data/vendor/libgit2/include/git2/filter.h +217 -0
  128. data/vendor/libgit2/include/git2/global.h +44 -0
  129. data/vendor/libgit2/include/git2/graph.h +17 -0
  130. data/vendor/libgit2/include/git2/ignore.h +2 -2
  131. data/vendor/libgit2/include/git2/index.h +269 -94
  132. data/vendor/libgit2/include/git2/indexer.h +44 -12
  133. data/vendor/libgit2/include/git2/mailmap.h +115 -0
  134. data/vendor/libgit2/include/git2/merge.h +501 -64
  135. data/vendor/libgit2/include/git2/message.h +52 -17
  136. data/vendor/libgit2/include/git2/net.h +11 -5
  137. data/vendor/libgit2/include/git2/notes.h +120 -16
  138. data/vendor/libgit2/include/git2/object.h +62 -23
  139. data/vendor/libgit2/include/git2/odb.h +140 -24
  140. data/vendor/libgit2/include/git2/odb_backend.h +56 -12
  141. data/vendor/libgit2/include/git2/oid.h +17 -18
  142. data/vendor/libgit2/include/git2/oidarray.h +40 -0
  143. data/vendor/libgit2/include/git2/pack.h +86 -7
  144. data/vendor/libgit2/include/git2/patch.h +274 -0
  145. data/vendor/libgit2/include/git2/pathspec.h +280 -0
  146. data/vendor/libgit2/include/git2/proxy.h +96 -0
  147. data/vendor/libgit2/include/git2/rebase.h +323 -0
  148. data/vendor/libgit2/include/git2/reflog.h +12 -9
  149. data/vendor/libgit2/include/git2/refs.h +241 -46
  150. data/vendor/libgit2/include/git2/refspec.h +20 -4
  151. data/vendor/libgit2/include/git2/remote.h +636 -209
  152. data/vendor/libgit2/include/git2/repository.h +267 -57
  153. data/vendor/libgit2/include/git2/reset.h +36 -6
  154. data/vendor/libgit2/include/git2/revert.h +91 -0
  155. data/vendor/libgit2/include/git2/revparse.h +27 -16
  156. data/vendor/libgit2/include/git2/revwalk.h +78 -35
  157. data/vendor/libgit2/include/git2/signature.h +32 -5
  158. data/vendor/libgit2/include/git2/stash.h +160 -21
  159. data/vendor/libgit2/include/git2/status.h +92 -30
  160. data/vendor/libgit2/include/git2/submodule.h +226 -133
  161. data/vendor/libgit2/include/git2/sys/alloc.h +101 -0
  162. data/vendor/libgit2/include/git2/sys/commit.h +38 -4
  163. data/vendor/libgit2/include/git2/sys/config.h +68 -9
  164. data/vendor/libgit2/include/git2/sys/diff.h +94 -0
  165. data/vendor/libgit2/include/git2/sys/filter.h +332 -0
  166. data/vendor/libgit2/include/git2/sys/hashsig.h +106 -0
  167. data/vendor/libgit2/include/git2/sys/index.h +6 -5
  168. data/vendor/libgit2/include/git2/sys/mempack.h +86 -0
  169. data/vendor/libgit2/include/git2/sys/merge.h +182 -0
  170. data/vendor/libgit2/include/git2/sys/odb_backend.h +66 -28
  171. data/vendor/libgit2/include/git2/sys/openssl.h +38 -0
  172. data/vendor/libgit2/include/git2/sys/path.h +64 -0
  173. data/vendor/libgit2/include/git2/sys/refdb_backend.h +79 -19
  174. data/vendor/libgit2/include/git2/sys/reflog.h +21 -0
  175. data/vendor/libgit2/include/git2/sys/refs.h +13 -2
  176. data/vendor/libgit2/include/git2/sys/repository.h +64 -1
  177. data/vendor/libgit2/include/git2/sys/stream.h +138 -0
  178. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  179. data/vendor/libgit2/include/git2/sys/transport.h +439 -0
  180. data/vendor/libgit2/include/git2/tag.h +11 -2
  181. data/vendor/libgit2/include/git2/trace.h +1 -1
  182. data/vendor/libgit2/include/git2/transaction.h +121 -0
  183. data/vendor/libgit2/include/git2/transport.h +261 -292
  184. data/vendor/libgit2/include/git2/tree.h +111 -21
  185. data/vendor/libgit2/include/git2/types.h +244 -32
  186. data/vendor/libgit2/include/git2/version.h +5 -2
  187. data/vendor/libgit2/include/git2/worktree.h +255 -0
  188. data/vendor/libgit2/include/git2.h +50 -40
  189. data/vendor/libgit2/libgit2.pc.in +13 -0
  190. data/vendor/libgit2/src/CMakeLists.txt +525 -0
  191. data/vendor/libgit2/src/alloc.c +55 -0
  192. data/vendor/libgit2/src/alloc.h +40 -0
  193. data/vendor/libgit2/src/annotated_commit.c +228 -0
  194. data/vendor/libgit2/src/annotated_commit.h +52 -0
  195. data/vendor/libgit2/src/apply.c +855 -0
  196. data/vendor/libgit2/src/apply.h +25 -0
  197. data/vendor/libgit2/src/array.h +74 -16
  198. data/vendor/libgit2/src/attr.c +239 -408
  199. data/vendor/libgit2/src/attr.h +3 -33
  200. data/vendor/libgit2/src/attr_file.c +424 -156
  201. data/vendor/libgit2/src/attr_file.h +95 -23
  202. data/vendor/libgit2/src/attrcache.c +469 -0
  203. data/vendor/libgit2/src/attrcache.h +37 -5
  204. data/vendor/libgit2/src/bitvec.h +75 -0
  205. data/vendor/libgit2/src/blame.c +532 -0
  206. data/vendor/libgit2/src/blame.h +95 -0
  207. data/vendor/libgit2/src/blame_git.c +668 -0
  208. data/vendor/libgit2/src/blame_git.h +22 -0
  209. data/vendor/libgit2/src/blob.c +233 -129
  210. data/vendor/libgit2/src/blob.h +29 -1
  211. data/vendor/libgit2/src/branch.c +295 -197
  212. data/vendor/libgit2/src/branch.h +2 -0
  213. data/vendor/libgit2/src/buf_text.c +52 -27
  214. data/vendor/libgit2/src/buf_text.h +7 -7
  215. data/vendor/libgit2/src/buffer.c +609 -52
  216. data/vendor/libgit2/src/buffer.h +68 -23
  217. data/vendor/libgit2/src/cache.c +48 -51
  218. data/vendor/libgit2/src/cache.h +6 -4
  219. data/vendor/libgit2/src/cc-compat.h +35 -7
  220. data/vendor/libgit2/src/checkout.c +1827 -483
  221. data/vendor/libgit2/src/checkout.h +4 -1
  222. data/vendor/libgit2/src/cherrypick.c +230 -0
  223. data/vendor/libgit2/src/clone.c +338 -258
  224. data/vendor/libgit2/src/{compress.h → clone.h} +5 -5
  225. data/vendor/libgit2/src/commit.c +711 -124
  226. data/vendor/libgit2/src/commit.h +10 -3
  227. data/vendor/libgit2/src/commit_list.c +21 -14
  228. data/vendor/libgit2/src/commit_list.h +9 -3
  229. data/vendor/libgit2/src/common.h +153 -13
  230. data/vendor/libgit2/src/config.c +871 -242
  231. data/vendor/libgit2/src/config.h +58 -14
  232. data/vendor/libgit2/src/config_backend.h +84 -0
  233. data/vendor/libgit2/src/config_cache.c +44 -18
  234. data/vendor/libgit2/src/config_entries.c +259 -0
  235. data/vendor/libgit2/src/config_entries.h +23 -0
  236. data/vendor/libgit2/src/config_file.c +837 -1113
  237. data/vendor/libgit2/src/config_mem.c +224 -0
  238. data/vendor/libgit2/src/config_parse.c +558 -0
  239. data/vendor/libgit2/src/config_parse.h +64 -0
  240. data/vendor/libgit2/src/crlf.c +290 -195
  241. data/vendor/libgit2/src/date.c +35 -7
  242. data/vendor/libgit2/src/delta.c +275 -71
  243. data/vendor/libgit2/src/delta.h +80 -58
  244. data/vendor/libgit2/src/describe.c +893 -0
  245. data/vendor/libgit2/src/diff.c +330 -1128
  246. data/vendor/libgit2/src/diff.h +25 -67
  247. data/vendor/libgit2/src/diff_driver.c +225 -109
  248. data/vendor/libgit2/src/diff_driver.h +5 -2
  249. data/vendor/libgit2/src/diff_file.c +128 -103
  250. data/vendor/libgit2/src/diff_file.h +17 -12
  251. data/vendor/libgit2/src/diff_generate.c +1622 -0
  252. data/vendor/libgit2/src/diff_generate.h +128 -0
  253. data/vendor/libgit2/src/diff_parse.c +108 -0
  254. data/vendor/libgit2/src/diff_parse.h +20 -0
  255. data/vendor/libgit2/src/diff_print.c +578 -218
  256. data/vendor/libgit2/src/diff_stats.c +362 -0
  257. data/vendor/libgit2/src/diff_tform.c +429 -257
  258. data/vendor/libgit2/src/diff_tform.h +25 -0
  259. data/vendor/libgit2/src/diff_xdiff.c +143 -46
  260. data/vendor/libgit2/src/diff_xdiff.h +12 -5
  261. data/vendor/libgit2/src/errors.c +150 -34
  262. data/vendor/libgit2/src/features.h.in +37 -0
  263. data/vendor/libgit2/src/fetch.c +69 -46
  264. data/vendor/libgit2/src/fetch.h +6 -12
  265. data/vendor/libgit2/src/fetchhead.c +40 -33
  266. data/vendor/libgit2/src/fetchhead.h +5 -4
  267. data/vendor/libgit2/src/filebuf.c +163 -61
  268. data/vendor/libgit2/src/filebuf.h +13 -7
  269. data/vendor/libgit2/src/fileops.c +549 -407
  270. data/vendor/libgit2/src/fileops.h +97 -106
  271. data/vendor/libgit2/src/filter.c +989 -46
  272. data/vendor/libgit2/src/filter.h +21 -70
  273. data/vendor/libgit2/src/fnmatch.c +67 -11
  274. data/vendor/libgit2/src/fnmatch.h +27 -7
  275. data/vendor/libgit2/src/global.c +257 -63
  276. data/vendor/libgit2/src/global.h +19 -0
  277. data/vendor/libgit2/src/graph.c +39 -23
  278. data/vendor/libgit2/src/hash/hash_collisiondetect.h +51 -0
  279. data/vendor/libgit2/src/hash/hash_common_crypto.h +61 -0
  280. data/vendor/libgit2/src/hash/hash_generic.c +3 -3
  281. data/vendor/libgit2/src/hash/hash_generic.h +10 -5
  282. data/vendor/libgit2/src/hash/hash_mbedtls.c +38 -0
  283. data/vendor/libgit2/src/hash/hash_mbedtls.h +24 -0
  284. data/vendor/libgit2/src/hash/hash_openssl.h +26 -8
  285. data/vendor/libgit2/src/hash/hash_win32.c +71 -43
  286. data/vendor/libgit2/src/hash/hash_win32.h +4 -3
  287. data/vendor/libgit2/src/hash/sha1dc/sha1.c +1900 -0
  288. data/vendor/libgit2/src/hash/sha1dc/sha1.h +110 -0
  289. data/vendor/libgit2/src/hash/sha1dc/ubc_check.c +372 -0
  290. data/vendor/libgit2/src/hash/sha1dc/ubc_check.h +52 -0
  291. data/vendor/libgit2/src/hash.c +0 -1
  292. data/vendor/libgit2/src/hash.h +13 -6
  293. data/vendor/libgit2/src/hashsig.c +121 -126
  294. data/vendor/libgit2/src/ident.c +129 -0
  295. data/vendor/libgit2/src/idxmap.c +153 -0
  296. data/vendor/libgit2/src/idxmap.h +41 -0
  297. data/vendor/libgit2/src/ignore.c +362 -123
  298. data/vendor/libgit2/src/ignore.h +16 -4
  299. data/vendor/libgit2/src/index.c +2131 -692
  300. data/vendor/libgit2/src/index.h +138 -6
  301. data/vendor/libgit2/src/indexer.c +866 -266
  302. data/vendor/libgit2/src/indexer.h +16 -0
  303. data/vendor/libgit2/src/integer.h +106 -0
  304. data/vendor/libgit2/src/iterator.c +1888 -967
  305. data/vendor/libgit2/src/iterator.h +130 -67
  306. data/vendor/libgit2/src/khash.h +43 -29
  307. data/vendor/libgit2/src/mailmap.c +485 -0
  308. data/vendor/libgit2/src/mailmap.h +35 -0
  309. data/vendor/libgit2/src/map.h +1 -1
  310. data/vendor/libgit2/src/merge.c +1679 -479
  311. data/vendor/libgit2/src/merge.h +89 -22
  312. data/vendor/libgit2/src/merge_driver.c +426 -0
  313. data/vendor/libgit2/src/merge_driver.h +62 -0
  314. data/vendor/libgit2/src/merge_file.c +238 -101
  315. data/vendor/libgit2/src/message.c +4 -28
  316. data/vendor/libgit2/src/message.h +3 -1
  317. data/vendor/libgit2/src/mwindow.c +123 -15
  318. data/vendor/libgit2/src/mwindow.h +10 -1
  319. data/vendor/libgit2/src/netops.c +178 -499
  320. data/vendor/libgit2/src/netops.h +51 -27
  321. data/vendor/libgit2/src/notes.c +251 -94
  322. data/vendor/libgit2/src/notes.h +5 -2
  323. data/vendor/libgit2/src/object.c +253 -67
  324. data/vendor/libgit2/src/object.h +40 -2
  325. data/vendor/libgit2/src/object_api.c +30 -11
  326. data/vendor/libgit2/src/odb.c +765 -201
  327. data/vendor/libgit2/src/odb.h +40 -8
  328. data/vendor/libgit2/src/odb_loose.c +560 -346
  329. data/vendor/libgit2/src/odb_mempack.c +185 -0
  330. data/vendor/libgit2/src/odb_pack.c +117 -73
  331. data/vendor/libgit2/src/offmap.c +113 -0
  332. data/vendor/libgit2/src/offmap.h +32 -42
  333. data/vendor/libgit2/src/oid.c +45 -25
  334. data/vendor/libgit2/src/oid.h +26 -8
  335. data/vendor/libgit2/src/oidarray.c +34 -0
  336. data/vendor/libgit2/src/oidarray.h +20 -0
  337. data/vendor/libgit2/src/oidmap.c +125 -0
  338. data/vendor/libgit2/src/oidmap.h +30 -17
  339. data/vendor/libgit2/src/pack-objects.c +688 -265
  340. data/vendor/libgit2/src/pack-objects.h +27 -13
  341. data/vendor/libgit2/src/pack.c +418 -202
  342. data/vendor/libgit2/src/pack.h +25 -16
  343. data/vendor/libgit2/src/parse.c +124 -0
  344. data/vendor/libgit2/src/parse.h +61 -0
  345. data/vendor/libgit2/src/patch.c +223 -0
  346. data/vendor/libgit2/src/patch.h +68 -0
  347. data/vendor/libgit2/src/patch_generate.c +901 -0
  348. data/vendor/libgit2/src/patch_generate.h +69 -0
  349. data/vendor/libgit2/src/patch_parse.c +1136 -0
  350. data/vendor/libgit2/src/patch_parse.h +51 -0
  351. data/vendor/libgit2/src/path.c +1247 -241
  352. data/vendor/libgit2/src/path.h +353 -57
  353. data/vendor/libgit2/src/pathspec.c +586 -58
  354. data/vendor/libgit2/src/pathspec.h +37 -15
  355. data/vendor/libgit2/src/pool.c +134 -221
  356. data/vendor/libgit2/src/pool.h +38 -50
  357. data/vendor/libgit2/src/posix.c +76 -10
  358. data/vendor/libgit2/src/posix.h +74 -32
  359. data/vendor/libgit2/src/pqueue.c +79 -117
  360. data/vendor/libgit2/src/pqueue.h +38 -82
  361. data/vendor/libgit2/src/proxy.c +39 -0
  362. data/vendor/libgit2/src/proxy.h +17 -0
  363. data/vendor/libgit2/src/push.c +178 -279
  364. data/vendor/libgit2/src/push.h +93 -4
  365. data/vendor/libgit2/src/reader.c +265 -0
  366. data/vendor/libgit2/src/reader.h +107 -0
  367. data/vendor/libgit2/src/rebase.c +1364 -0
  368. data/vendor/libgit2/src/refdb.c +74 -19
  369. data/vendor/libgit2/src/refdb.h +16 -3
  370. data/vendor/libgit2/src/refdb_fs.c +1472 -603
  371. data/vendor/libgit2/src/refdb_fs.h +4 -0
  372. data/vendor/libgit2/src/reflog.c +40 -330
  373. data/vendor/libgit2/src/reflog.h +8 -2
  374. data/vendor/libgit2/src/refs.c +641 -225
  375. data/vendor/libgit2/src/refs.h +53 -6
  376. data/vendor/libgit2/src/refspec.c +175 -62
  377. data/vendor/libgit2/src/refspec.h +10 -25
  378. data/vendor/libgit2/src/remote.c +1741 -723
  379. data/vendor/libgit2/src/remote.h +17 -5
  380. data/vendor/libgit2/src/repository.c +1505 -421
  381. data/vendor/libgit2/src/repository.h +95 -15
  382. data/vendor/libgit2/src/reset.c +63 -26
  383. data/vendor/libgit2/src/revert.c +232 -0
  384. data/vendor/libgit2/src/revparse.c +94 -80
  385. data/vendor/libgit2/src/revwalk.c +427 -194
  386. data/vendor/libgit2/src/revwalk.h +14 -5
  387. data/vendor/libgit2/src/settings.c +290 -0
  388. data/vendor/libgit2/src/sha1_lookup.c +16 -159
  389. data/vendor/libgit2/src/sha1_lookup.h +5 -4
  390. data/vendor/libgit2/src/signature.c +138 -26
  391. data/vendor/libgit2/src/signature.h +5 -0
  392. data/vendor/libgit2/src/sortedcache.c +395 -0
  393. data/vendor/libgit2/src/sortedcache.h +180 -0
  394. data/vendor/libgit2/src/stash.c +629 -168
  395. data/vendor/libgit2/src/status.c +125 -75
  396. data/vendor/libgit2/src/status.h +4 -2
  397. data/vendor/libgit2/src/stdalloc.c +120 -0
  398. data/vendor/libgit2/src/stdalloc.h +17 -0
  399. data/vendor/libgit2/src/stream.h +86 -0
  400. data/vendor/libgit2/src/streams/mbedtls.c +483 -0
  401. data/vendor/libgit2/src/streams/mbedtls.h +23 -0
  402. data/vendor/libgit2/src/streams/openssl.c +789 -0
  403. data/vendor/libgit2/src/streams/openssl.h +23 -0
  404. data/vendor/libgit2/src/streams/registry.c +118 -0
  405. data/vendor/libgit2/src/streams/registry.h +19 -0
  406. data/vendor/libgit2/src/streams/socket.c +235 -0
  407. data/vendor/libgit2/src/streams/socket.h +23 -0
  408. data/vendor/libgit2/src/streams/stransport.c +323 -0
  409. data/vendor/libgit2/src/streams/stransport.h +21 -0
  410. data/vendor/libgit2/src/streams/tls.c +73 -0
  411. data/vendor/libgit2/src/streams/tls.h +31 -0
  412. data/vendor/libgit2/src/strmap.c +147 -0
  413. data/vendor/libgit2/src/strmap.h +46 -51
  414. data/vendor/libgit2/src/strnlen.h +24 -0
  415. data/vendor/libgit2/src/submodule.c +1633 -877
  416. data/vendor/libgit2/src/submodule.h +83 -21
  417. data/vendor/libgit2/src/sysdir.c +355 -0
  418. data/vendor/libgit2/src/sysdir.h +119 -0
  419. data/vendor/libgit2/src/tag.c +87 -62
  420. data/vendor/libgit2/src/tag.h +4 -1
  421. data/vendor/libgit2/src/thread-utils.c +3 -0
  422. data/vendor/libgit2/src/thread-utils.h +71 -35
  423. data/vendor/libgit2/src/trace.c +4 -4
  424. data/vendor/libgit2/src/trace.h +11 -3
  425. data/vendor/libgit2/src/trailer.c +416 -0
  426. data/vendor/libgit2/src/transaction.c +382 -0
  427. data/vendor/libgit2/src/transaction.h +14 -0
  428. data/vendor/libgit2/src/transport.c +133 -67
  429. data/vendor/libgit2/src/transports/auth.c +75 -0
  430. data/vendor/libgit2/src/transports/auth.h +64 -0
  431. data/vendor/libgit2/src/transports/auth_negotiate.c +277 -0
  432. data/vendor/libgit2/src/transports/auth_negotiate.h +27 -0
  433. data/vendor/libgit2/src/transports/cred.c +296 -68
  434. data/vendor/libgit2/src/transports/cred.h +16 -0
  435. data/vendor/libgit2/src/transports/cred_helpers.c +4 -0
  436. data/vendor/libgit2/src/transports/git.c +108 -90
  437. data/vendor/libgit2/src/transports/http.c +803 -258
  438. data/vendor/libgit2/src/transports/http.h +25 -0
  439. data/vendor/libgit2/src/transports/local.c +265 -169
  440. data/vendor/libgit2/src/transports/smart.c +255 -45
  441. data/vendor/libgit2/src/transports/smart.h +42 -22
  442. data/vendor/libgit2/src/transports/smart_pkt.c +250 -159
  443. data/vendor/libgit2/src/transports/smart_protocol.c +414 -196
  444. data/vendor/libgit2/src/transports/ssh.c +645 -236
  445. data/vendor/libgit2/src/transports/ssh.h +14 -0
  446. data/vendor/libgit2/src/transports/winhttp.c +809 -353
  447. data/vendor/libgit2/src/tree-cache.c +138 -52
  448. data/vendor/libgit2/src/tree-cache.h +14 -7
  449. data/vendor/libgit2/src/tree.c +620 -259
  450. data/vendor/libgit2/src/tree.h +12 -19
  451. data/vendor/libgit2/src/tsort.c +3 -2
  452. data/vendor/libgit2/src/unix/map.c +25 -7
  453. data/vendor/libgit2/src/unix/posix.h +77 -12
  454. data/vendor/libgit2/src/unix/pthread.h +56 -0
  455. data/vendor/libgit2/src/unix/realpath.c +12 -8
  456. data/vendor/libgit2/src/userdiff.h +208 -0
  457. data/vendor/libgit2/src/util.c +349 -165
  458. data/vendor/libgit2/src/util.h +167 -85
  459. data/vendor/libgit2/src/varint.c +43 -0
  460. data/vendor/libgit2/src/varint.h +17 -0
  461. data/vendor/libgit2/src/vector.c +156 -33
  462. data/vendor/libgit2/src/vector.h +41 -5
  463. data/vendor/libgit2/src/win32/dir.c +22 -42
  464. data/vendor/libgit2/src/win32/dir.h +7 -5
  465. data/vendor/libgit2/src/win32/error.c +6 -32
  466. data/vendor/libgit2/src/win32/error.h +4 -2
  467. data/vendor/libgit2/src/win32/findfile.c +62 -69
  468. data/vendor/libgit2/src/win32/findfile.h +5 -13
  469. data/vendor/libgit2/src/win32/git2.rc +44 -0
  470. data/vendor/libgit2/src/win32/map.c +39 -11
  471. data/vendor/libgit2/src/win32/mingw-compat.h +10 -11
  472. data/vendor/libgit2/src/win32/msvc-compat.h +10 -33
  473. data/vendor/libgit2/src/win32/path_w32.c +476 -0
  474. data/vendor/libgit2/src/win32/path_w32.h +104 -0
  475. data/vendor/libgit2/src/win32/posix.h +35 -30
  476. data/vendor/libgit2/src/win32/posix_w32.c +659 -327
  477. data/vendor/libgit2/src/win32/precompiled.h +7 -2
  478. data/vendor/libgit2/src/win32/reparse.h +57 -0
  479. data/vendor/libgit2/src/win32/thread.c +258 -0
  480. data/vendor/libgit2/src/win32/thread.h +64 -0
  481. data/vendor/libgit2/src/win32/utf-conv.c +127 -62
  482. data/vendor/libgit2/src/win32/utf-conv.h +47 -6
  483. data/vendor/libgit2/src/win32/version.h +21 -4
  484. data/vendor/libgit2/src/win32/w32_buffer.c +54 -0
  485. data/vendor/libgit2/src/win32/w32_buffer.h +20 -0
  486. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +438 -0
  487. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +129 -0
  488. data/vendor/libgit2/src/win32/w32_stack.c +193 -0
  489. data/vendor/libgit2/src/win32/w32_stack.h +140 -0
  490. data/vendor/libgit2/src/win32/w32_util.c +95 -0
  491. data/vendor/libgit2/src/win32/w32_util.h +170 -0
  492. data/vendor/libgit2/src/win32/win32-compat.h +52 -0
  493. data/vendor/libgit2/src/worktree.c +578 -0
  494. data/vendor/libgit2/src/worktree.h +39 -0
  495. data/vendor/libgit2/src/xdiff/xdiff.h +33 -18
  496. data/vendor/libgit2/src/xdiff/xdiffi.c +578 -88
  497. data/vendor/libgit2/src/xdiff/xdiffi.h +3 -2
  498. data/vendor/libgit2/src/xdiff/xemit.c +106 -45
  499. data/vendor/libgit2/src/xdiff/xemit.h +3 -3
  500. data/vendor/libgit2/src/xdiff/xhistogram.c +5 -4
  501. data/vendor/libgit2/src/xdiff/xinclude.h +3 -2
  502. data/vendor/libgit2/src/xdiff/xmacros.h +2 -2
  503. data/vendor/libgit2/src/xdiff/xmerge.c +167 -48
  504. data/vendor/libgit2/src/xdiff/xpatience.c +42 -10
  505. data/vendor/libgit2/src/xdiff/xprepare.c +14 -14
  506. data/vendor/libgit2/src/xdiff/xprepare.h +2 -2
  507. data/vendor/libgit2/src/xdiff/xtypes.h +2 -2
  508. data/vendor/libgit2/src/xdiff/xutils.c +60 -56
  509. data/vendor/libgit2/src/xdiff/xutils.h +3 -5
  510. data/vendor/libgit2/src/zstream.c +205 -0
  511. data/vendor/libgit2/src/zstream.h +53 -0
  512. metadata +281 -233
  513. data/Rakefile +0 -61
  514. data/ext/rugged/rugged_diff_patch.c +0 -169
  515. data/lib/rugged/diff/patch.rb +0 -28
  516. data/test/blob_test.rb +0 -341
  517. data/test/branch_test.rb +0 -199
  518. data/test/commit_test.rb +0 -104
  519. data/test/config_test.rb +0 -45
  520. data/test/coverage/cover.rb +0 -133
  521. data/test/diff_test.rb +0 -777
  522. data/test/errors_test.rb +0 -34
  523. data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
  524. data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
  525. data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
  526. data/test/fixtures/archive.tar.gz +0 -0
  527. data/test/fixtures/attr/attr0 +0 -1
  528. data/test/fixtures/attr/attr1 +0 -29
  529. data/test/fixtures/attr/attr2 +0 -21
  530. data/test/fixtures/attr/attr3 +0 -4
  531. data/test/fixtures/attr/binfile +0 -1
  532. data/test/fixtures/attr/dir/file +0 -0
  533. data/test/fixtures/attr/file +0 -1
  534. data/test/fixtures/attr/gitattributes +0 -29
  535. data/test/fixtures/attr/gitignore +0 -2
  536. data/test/fixtures/attr/ign +0 -1
  537. data/test/fixtures/attr/macro_bad +0 -1
  538. data/test/fixtures/attr/macro_test +0 -1
  539. data/test/fixtures/attr/root_test1 +0 -1
  540. data/test/fixtures/attr/root_test2 +0 -6
  541. data/test/fixtures/attr/root_test3 +0 -19
  542. data/test/fixtures/attr/root_test4.txt +0 -14
  543. data/test/fixtures/attr/sub/abc +0 -37
  544. data/test/fixtures/attr/sub/dir/file +0 -0
  545. data/test/fixtures/attr/sub/file +0 -1
  546. data/test/fixtures/attr/sub/ign/file +0 -1
  547. data/test/fixtures/attr/sub/ign/sub/file +0 -1
  548. data/test/fixtures/attr/sub/sub/dir +0 -0
  549. data/test/fixtures/attr/sub/sub/file +0 -1
  550. data/test/fixtures/attr/sub/sub/subsub.txt +0 -1
  551. data/test/fixtures/attr/sub/subdir_test1 +0 -2
  552. data/test/fixtures/attr/sub/subdir_test2.txt +0 -1
  553. data/test/fixtures/diff/another.txt +0 -38
  554. data/test/fixtures/diff/readme.txt +0 -36
  555. data/test/fixtures/mergedrepo/conflicts-one.txt +0 -5
  556. data/test/fixtures/mergedrepo/conflicts-two.txt +0 -5
  557. data/test/fixtures/mergedrepo/one.txt +0 -10
  558. data/test/fixtures/mergedrepo/two.txt +0 -12
  559. data/test/fixtures/status/current_file +0 -1
  560. data/test/fixtures/status/ignored_file +0 -1
  561. data/test/fixtures/status/modified_file +0 -2
  562. data/test/fixtures/status/new_file +0 -1
  563. data/test/fixtures/status/staged_changes +0 -2
  564. data/test/fixtures/status/staged_changes_modified_file +0 -3
  565. data/test/fixtures/status/staged_delete_modified_file +0 -1
  566. data/test/fixtures/status/staged_new_file +0 -1
  567. data/test/fixtures/status/staged_new_file_modified_file +0 -2
  568. data/test/fixtures/status/subdir/current_file +0 -1
  569. data/test/fixtures/status/subdir/modified_file +0 -2
  570. data/test/fixtures/status/subdir/new_file +0 -1
  571. data/test/fixtures/status/subdir.txt +0 -2
  572. data/test/fixtures/status//350/277/231 +0 -1
  573. data/test/fixtures/testrepo.git/HEAD +0 -1
  574. data/test/fixtures/testrepo.git/config +0 -13
  575. data/test/fixtures/testrepo.git/description +0 -1
  576. data/test/fixtures/testrepo.git/index +0 -0
  577. data/test/fixtures/testrepo.git/info/exclude +0 -6
  578. data/test/fixtures/testrepo.git/logs/HEAD +0 -3
  579. data/test/fixtures/testrepo.git/logs/refs/heads/master +0 -3
  580. data/test/fixtures/testrepo.git/logs/refs/notes/commits +0 -1
  581. data/test/fixtures/testrepo.git/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d +0 -0
  582. data/test/fixtures/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 +0 -0
  583. data/test/fixtures/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 +0 -0
  584. data/test/fixtures/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd +0 -0
  585. data/test/fixtures/testrepo.git/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 +0 -0
  586. data/test/fixtures/testrepo.git/objects/36/060c58702ed4c2a40832c51758d5344201d89a +0 -2
  587. data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +0 -1
  588. data/test/fixtures/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 +0 -0
  589. data/test/fixtures/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +0 -2
  590. data/test/fixtures/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +0 -2
  591. data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
  592. data/test/fixtures/testrepo.git/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 +0 -0
  593. data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +0 -1
  594. data/test/fixtures/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a +0 -0
  595. data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
  596. data/test/fixtures/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d +0 -0
  597. data/test/fixtures/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 +0 -0
  598. data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
  599. data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
  600. data/test/fixtures/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +0 -3
  601. data/test/fixtures/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +0 -2
  602. data/test/fixtures/testrepo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd +0 -0
  603. data/test/fixtures/testrepo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 +0 -0
  604. data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +0 -3
  605. data/test/fixtures/testrepo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 +0 -3
  606. data/test/fixtures/testrepo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd +0 -3
  607. data/test/fixtures/testrepo.git/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b +0 -0
  608. data/test/fixtures/testrepo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  609. data/test/fixtures/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 +0 -0
  610. data/test/fixtures/testrepo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 +0 -0
  611. data/test/fixtures/testrepo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 +0 -0
  612. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx +0 -0
  613. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack +0 -0
  614. data/test/fixtures/testrepo.git/packed-refs +0 -2
  615. data/test/fixtures/testrepo.git/refs/heads/master +0 -1
  616. data/test/fixtures/testrepo.git/refs/notes/commits +0 -1
  617. data/test/fixtures/testrepo.git/refs/tags/v0.9 +0 -1
  618. data/test/fixtures/testrepo.git/refs/tags/v1.0 +0 -1
  619. data/test/fixtures/text_file.md +0 -464
  620. data/test/fixtures/unsymlinked.git/HEAD +0 -1
  621. data/test/fixtures/unsymlinked.git/config +0 -6
  622. data/test/fixtures/unsymlinked.git/description +0 -1
  623. data/test/fixtures/unsymlinked.git/info/exclude +0 -2
  624. data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
  625. data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
  626. data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
  627. data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
  628. data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
  629. data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
  630. data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
  631. data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
  632. data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
  633. data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +0 -2
  634. data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
  635. data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
  636. data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
  637. data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
  638. data/test/fixtures/unsymlinked.git/refs/heads/exe-file +0 -1
  639. data/test/fixtures/unsymlinked.git/refs/heads/master +0 -1
  640. data/test/fixtures/unsymlinked.git/refs/heads/reg-file +0 -1
  641. data/test/index_test.rb +0 -333
  642. data/test/lib_test.rb +0 -127
  643. data/test/note_test.rb +0 -158
  644. data/test/object_test.rb +0 -43
  645. data/test/reference_test.rb +0 -207
  646. data/test/remote_test.rb +0 -324
  647. data/test/repo_pack_test.rb +0 -24
  648. data/test/repo_reset_test.rb +0 -82
  649. data/test/repo_test.rb +0 -402
  650. data/test/tag_test.rb +0 -68
  651. data/test/test_helper.rb +0 -92
  652. data/test/tree_test.rb +0 -91
  653. data/test/walker_test.rb +0 -88
  654. data/vendor/libgit2/Makefile.embed +0 -42
  655. data/vendor/libgit2/include/git2/push.h +0 -131
  656. data/vendor/libgit2/include/git2/threads.h +0 -50
  657. data/vendor/libgit2/src/amiga/map.c +0 -48
  658. data/vendor/libgit2/src/bswap.h +0 -97
  659. data/vendor/libgit2/src/compress.c +0 -53
  660. data/vendor/libgit2/src/config_file.h +0 -60
  661. data/vendor/libgit2/src/delta-apply.c +0 -134
  662. data/vendor/libgit2/src/delta-apply.h +0 -50
  663. data/vendor/libgit2/src/diff_patch.c +0 -995
  664. data/vendor/libgit2/src/diff_patch.h +0 -46
  665. data/vendor/libgit2/src/hashsig.h +0 -72
  666. data/vendor/libgit2/src/merge_file.h +0 -71
  667. data/vendor/libgit2/src/win32/pthread.c +0 -144
  668. data/vendor/libgit2/src/win32/pthread.h +0 -50
@@ -4,28 +4,67 @@
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
- #include <stdarg.h>
7
+
8
+ #include "repository.h"
9
+
8
10
  #include <ctype.h>
9
11
 
10
12
  #include "git2/object.h"
11
- #include "git2/refdb.h"
12
13
  #include "git2/sys/repository.h"
13
14
 
14
15
  #include "common.h"
15
- #include "repository.h"
16
16
  #include "commit.h"
17
17
  #include "tag.h"
18
18
  #include "blob.h"
19
19
  #include "fileops.h"
20
+ #include "sysdir.h"
20
21
  #include "filebuf.h"
21
22
  #include "index.h"
22
23
  #include "config.h"
23
24
  #include "refs.h"
24
25
  #include "filter.h"
25
26
  #include "odb.h"
27
+ #include "refdb.h"
26
28
  #include "remote.h"
27
29
  #include "merge.h"
28
30
  #include "diff_driver.h"
31
+ #include "annotated_commit.h"
32
+ #include "submodule.h"
33
+ #include "worktree.h"
34
+
35
+ #include "strmap.h"
36
+
37
+ #ifdef GIT_WIN32
38
+ # include "win32/w32_util.h"
39
+ #endif
40
+
41
+ bool git_repository__fsync_gitdir = false;
42
+
43
+ static const struct {
44
+ git_repository_item_t parent;
45
+ const char *name;
46
+ bool directory;
47
+ } items[] = {
48
+ { GIT_REPOSITORY_ITEM_GITDIR, NULL, true },
49
+ { GIT_REPOSITORY_ITEM_WORKDIR, NULL, true },
50
+ { GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true },
51
+ { GIT_REPOSITORY_ITEM_GITDIR, "index", false },
52
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true },
53
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true },
54
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false },
55
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true },
56
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "config", false },
57
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "info", true },
58
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true },
59
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true },
60
+ { GIT_REPOSITORY_ITEM_GITDIR, "modules", true },
61
+ { GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true }
62
+ };
63
+
64
+ static int check_repositoryformatversion(git_config *config);
65
+
66
+ #define GIT_COMMONDIR_FILE "commondir"
67
+ #define GIT_GITDIR_FILE "gitdir"
29
68
 
30
69
  #define GIT_FILE_CONTENT_PREFIX "gitdir:"
31
70
 
@@ -33,7 +72,16 @@
33
72
 
34
73
  #define GIT_REPO_VERSION 0
35
74
 
36
- #define GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
75
+ git_buf git_repository__reserved_names_win32[] = {
76
+ { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
77
+ { GIT_DIR_SHORTNAME, 0, CONST_STRLEN(GIT_DIR_SHORTNAME) }
78
+ };
79
+ size_t git_repository__reserved_names_win32_len = 2;
80
+
81
+ git_buf git_repository__reserved_names_posix[] = {
82
+ { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
83
+ };
84
+ size_t git_repository__reserved_names_posix_len = 1;
37
85
 
38
86
  static void set_odb(git_repository *repo, git_odb *odb)
39
87
  {
@@ -93,6 +141,7 @@ void git_repository__cleanup(git_repository *repo)
93
141
  {
94
142
  assert(repo);
95
143
 
144
+ git_repository_submodule_cache_clear(repo);
96
145
  git_cache_clear(&repo->objects);
97
146
  git_attr_cache_flush(repo);
98
147
 
@@ -104,20 +153,29 @@ void git_repository__cleanup(git_repository *repo)
104
153
 
105
154
  void git_repository_free(git_repository *repo)
106
155
  {
156
+ size_t i;
157
+
107
158
  if (repo == NULL)
108
159
  return;
109
160
 
110
161
  git_repository__cleanup(repo);
111
162
 
112
163
  git_cache_free(&repo->objects);
113
- git_submodule_config_free(repo);
114
164
 
115
165
  git_diff_driver_registry_free(repo->diff_drivers);
116
166
  repo->diff_drivers = NULL;
117
167
 
118
- git__free(repo->path_repository);
168
+ for (i = 0; i < repo->reserved_names.size; i++)
169
+ git_buf_dispose(git_array_get(repo->reserved_names, i));
170
+ git_array_clear(repo->reserved_names);
171
+
172
+ git__free(repo->gitlink);
173
+ git__free(repo->gitdir);
174
+ git__free(repo->commondir);
119
175
  git__free(repo->workdir);
120
176
  git__free(repo->namespace);
177
+ git__free(repo->ident_name);
178
+ git__free(repo->ident_email);
121
179
 
122
180
  git__memzero(repo, sizeof(*repo));
123
181
  git__free(repo);
@@ -128,17 +186,41 @@ void git_repository_free(git_repository *repo)
128
186
  *
129
187
  * Open a repository object from its path
130
188
  */
131
- static bool valid_repository_path(git_buf *repository_path)
189
+ static bool valid_repository_path(git_buf *repository_path, git_buf *common_path)
132
190
  {
133
- /* Check OBJECTS_DIR first, since it will generate the longest path name */
134
- if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false)
135
- return false;
191
+ /* Check if we have a separate commondir (e.g. we have a
192
+ * worktree) */
193
+ if (git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) {
194
+ git_buf common_link = GIT_BUF_INIT;
195
+ git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE);
196
+
197
+ git_futils_readbuffer(&common_link, common_link.ptr);
198
+ git_buf_rtrim(&common_link);
199
+
200
+ if (git_path_is_relative(common_link.ptr)) {
201
+ git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr);
202
+ } else {
203
+ git_buf_swap(common_path, &common_link);
204
+ }
205
+
206
+ git_buf_dispose(&common_link);
207
+ }
208
+ else {
209
+ git_buf_set(common_path, repository_path->ptr, repository_path->size);
210
+ }
211
+
212
+ /* Make sure the commondir path always has a trailing * slash */
213
+ if (git_buf_rfind(common_path, '/') != (ssize_t)common_path->size - 1)
214
+ git_buf_putc(common_path, '/');
136
215
 
137
216
  /* Ensure HEAD file exists */
138
217
  if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
139
218
  return false;
140
219
 
141
- if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false)
220
+ /* Check files in common dir */
221
+ if (git_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false)
222
+ return false;
223
+ if (git_path_contains_dir(common_path, GIT_REFS_DIR) == false)
142
224
  return false;
143
225
 
144
226
  return true;
@@ -147,81 +229,113 @@ static bool valid_repository_path(git_buf *repository_path)
147
229
  static git_repository *repository_alloc(void)
148
230
  {
149
231
  git_repository *repo = git__calloc(1, sizeof(git_repository));
150
- if (!repo)
151
- return NULL;
152
232
 
153
- if (git_cache_init(&repo->objects) < 0) {
154
- git__free(repo);
155
- return NULL;
156
- }
233
+ if (repo == NULL ||
234
+ git_cache_init(&repo->objects) < 0)
235
+ goto on_error;
236
+
237
+ git_array_init_to_size(repo->reserved_names, 4);
238
+ if (!repo->reserved_names.ptr)
239
+ goto on_error;
157
240
 
158
241
  /* set all the entries in the cvar cache to `unset` */
159
242
  git_repository__cvar_cache_clear(repo);
160
243
 
161
244
  return repo;
245
+
246
+ on_error:
247
+ if (repo)
248
+ git_cache_free(&repo->objects);
249
+
250
+ git__free(repo);
251
+ return NULL;
162
252
  }
163
253
 
164
254
  int git_repository_new(git_repository **out)
165
255
  {
166
- *out = repository_alloc();
256
+ git_repository *repo;
257
+
258
+ *out = repo = repository_alloc();
259
+ GIT_ERROR_CHECK_ALLOC(repo);
260
+
261
+ repo->is_bare = 1;
262
+ repo->is_worktree = 0;
263
+
167
264
  return 0;
168
265
  }
169
266
 
170
- static int load_config_data(git_repository *repo)
267
+ static int load_config_data(git_repository *repo, const git_config *config)
171
268
  {
172
269
  int is_bare;
173
- git_config *config;
174
270
 
175
- if (git_repository_config__weakptr(&config, repo) < 0)
176
- return -1;
271
+ int err = git_config_get_bool(&is_bare, config, "core.bare");
272
+ if (err < 0 && err != GIT_ENOTFOUND)
273
+ return err;
177
274
 
178
275
  /* Try to figure out if it's bare, default to non-bare if it's not set */
179
- if (git_config_get_bool(&is_bare, config, "core.bare") < 0)
180
- repo->is_bare = 0;
276
+ if (err != GIT_ENOTFOUND)
277
+ repo->is_bare = is_bare && !repo->is_worktree;
181
278
  else
182
- repo->is_bare = is_bare;
279
+ repo->is_bare = 0;
183
280
 
184
281
  return 0;
185
282
  }
186
283
 
187
- static int load_workdir(git_repository *repo, git_buf *parent_path)
284
+ static int load_workdir(git_repository *repo, git_config *config, git_buf *parent_path)
188
285
  {
189
- int error;
190
- git_config *config;
191
- const char *worktree;
192
- git_buf worktree_buf = GIT_BUF_INIT;
286
+ int error;
287
+ git_config_entry *ce;
288
+ git_buf worktree = GIT_BUF_INIT;
289
+ git_buf path = GIT_BUF_INIT;
193
290
 
194
291
  if (repo->is_bare)
195
292
  return 0;
196
293
 
197
- if (git_repository_config__weakptr(&config, repo) < 0)
198
- return -1;
199
-
200
- error = git_config_get_string(&worktree, config, "core.worktree");
201
- if (!error && worktree != NULL) {
202
- error = git_path_prettify_dir(
203
- &worktree_buf, worktree, repo->path_repository);
204
- if (error < 0)
205
- return error;
206
- repo->workdir = git_buf_detach(&worktree_buf);
207
- }
208
- else if (error != GIT_ENOTFOUND)
294
+ if ((error = git_config__lookup_entry(
295
+ &ce, config, "core.worktree", false)) < 0)
209
296
  return error;
210
- else {
211
- giterr_clear();
212
297
 
213
- if (parent_path && git_path_isdir(parent_path->ptr))
214
- repo->workdir = git_buf_detach(parent_path);
215
- else {
216
- git_path_dirname_r(&worktree_buf, repo->path_repository);
217
- git_path_to_dir(&worktree_buf);
218
- repo->workdir = git_buf_detach(&worktree_buf);
298
+ if (repo->is_worktree) {
299
+ char *gitlink = git_worktree__read_link(repo->gitdir, GIT_GITDIR_FILE);
300
+ if (!gitlink) {
301
+ error = -1;
302
+ goto cleanup;
219
303
  }
304
+
305
+ git_buf_attach(&worktree, gitlink, 0);
306
+
307
+ if ((git_path_dirname_r(&worktree, worktree.ptr)) < 0 ||
308
+ git_path_to_dir(&worktree) < 0) {
309
+ error = -1;
310
+ goto cleanup;
311
+ }
312
+
313
+ repo->workdir = git_buf_detach(&worktree);
314
+ }
315
+ else if (ce && ce->value) {
316
+ if ((error = git_path_prettify_dir(
317
+ &worktree, ce->value, repo->gitdir)) < 0)
318
+ goto cleanup;
319
+
320
+ repo->workdir = git_buf_detach(&worktree);
220
321
  }
322
+ else if (parent_path && git_path_isdir(parent_path->ptr))
323
+ repo->workdir = git_buf_detach(parent_path);
324
+ else {
325
+ if (git_path_dirname_r(&worktree, repo->gitdir) < 0 ||
326
+ git_path_to_dir(&worktree) < 0) {
327
+ error = -1;
328
+ goto cleanup;
329
+ }
221
330
 
222
- GITERR_CHECK_ALLOC(repo->workdir);
331
+ repo->workdir = git_buf_detach(&worktree);
332
+ }
223
333
 
224
- return 0;
334
+ GIT_ERROR_CHECK_ALLOC(repo->workdir);
335
+ cleanup:
336
+ git_buf_dispose(&path);
337
+ git_config_entry_free(ce);
338
+ return error;
225
339
  }
226
340
 
227
341
  /*
@@ -232,7 +346,7 @@ static int load_workdir(git_repository *repo, git_buf *parent_path)
232
346
  * the stack could remove directories name limits, but at the cost of doing
233
347
  * repeated malloc/frees inside the loop below, so let's not do it now.
234
348
  */
235
- static int find_ceiling_dir_offset(
349
+ static size_t find_ceiling_dir_offset(
236
350
  const char *path,
237
351
  const char *ceiling_directories)
238
352
  {
@@ -246,7 +360,7 @@ static int find_ceiling_dir_offset(
246
360
  min_len = (size_t)(git_path_root(path) + 1);
247
361
 
248
362
  if (ceiling_directories == NULL || min_len == 0)
249
- return (int)min_len;
363
+ return min_len;
250
364
 
251
365
  for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
252
366
  for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
@@ -266,14 +380,14 @@ static int find_ceiling_dir_offset(
266
380
  buf[--len] = '\0';
267
381
 
268
382
  if (!strncmp(path, buf2, len) &&
269
- path[len] == '/' &&
383
+ (path[len] == '/' || !path[len]) &&
270
384
  len > max_len)
271
385
  {
272
386
  max_len = len;
273
387
  }
274
388
  }
275
389
 
276
- return (int)(max_len <= min_len ? min_len : max_len);
390
+ return (max_len <= min_len ? min_len : max_len);
277
391
  }
278
392
 
279
393
  /*
@@ -293,116 +407,158 @@ static int read_gitfile(git_buf *path_out, const char *file_path)
293
407
  return -1;
294
408
 
295
409
  git_buf_rtrim(&file);
410
+ /* apparently on Windows, some people use backslashes in paths */
411
+ git_path_mkposix(file.ptr);
296
412
 
297
413
  if (git_buf_len(&file) <= prefix_len ||
298
414
  memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
299
415
  {
300
- giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path);
416
+ git_error_set(GIT_ERROR_REPOSITORY,
417
+ "the `.git` file at '%s' is malformed", file_path);
301
418
  error = -1;
302
419
  }
303
420
  else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
304
421
  const char *gitlink = git_buf_cstr(&file) + prefix_len;
305
422
  while (*gitlink && git__isspace(*gitlink)) gitlink++;
423
+
306
424
  error = git_path_prettify_dir(
307
425
  path_out, gitlink, git_buf_cstr(path_out));
308
426
  }
309
427
 
310
- git_buf_free(&file);
428
+ git_buf_dispose(&file);
311
429
  return error;
312
430
  }
313
431
 
314
432
  static int find_repo(
315
- git_buf *repo_path,
316
- git_buf *parent_path,
433
+ git_buf *gitdir_path,
434
+ git_buf *workdir_path,
435
+ git_buf *gitlink_path,
436
+ git_buf *commondir_path,
317
437
  const char *start_path,
318
438
  uint32_t flags,
319
439
  const char *ceiling_dirs)
320
440
  {
321
441
  int error;
322
442
  git_buf path = GIT_BUF_INIT;
443
+ git_buf repo_link = GIT_BUF_INIT;
444
+ git_buf common_link = GIT_BUF_INIT;
323
445
  struct stat st;
324
446
  dev_t initial_device = 0;
325
- bool try_with_dot_git = false;
326
- int ceiling_offset;
447
+ int min_iterations;
448
+ bool in_dot_git;
449
+ size_t ceiling_offset = 0;
327
450
 
328
- git_buf_free(repo_path);
451
+ git_buf_clear(gitdir_path);
329
452
 
330
- if ((error = git_path_prettify_dir(&path, start_path, NULL)) < 0)
453
+ error = git_path_prettify(&path, start_path, NULL);
454
+ if (error < 0)
331
455
  return error;
332
456
 
333
- ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
457
+ /* in_dot_git toggles each loop:
458
+ * /a/b/c/.git, /a/b/c, /a/b/.git, /a/b, /a/.git, /a
459
+ * With GIT_REPOSITORY_OPEN_BARE or GIT_REPOSITORY_OPEN_NO_DOTGIT, we
460
+ * assume we started with /a/b/c.git and don't append .git the first
461
+ * time through.
462
+ * min_iterations indicates the number of iterations left before going
463
+ * further counts as a search. */
464
+ if (flags & (GIT_REPOSITORY_OPEN_BARE | GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
465
+ in_dot_git = true;
466
+ min_iterations = 1;
467
+ } else {
468
+ in_dot_git = false;
469
+ min_iterations = 2;
470
+ }
334
471
 
335
- if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
336
- return error;
472
+ for (;;) {
473
+ if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
474
+ if (!in_dot_git) {
475
+ error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
476
+ if (error < 0)
477
+ break;
478
+ }
479
+ in_dot_git = !in_dot_git;
480
+ }
337
481
 
338
- while (!error && !git_buf_len(repo_path)) {
339
482
  if (p_stat(path.ptr, &st) == 0) {
340
483
  /* check that we have not crossed device boundaries */
341
484
  if (initial_device == 0)
342
485
  initial_device = st.st_dev;
343
486
  else if (st.st_dev != initial_device &&
344
- (flags & GIT_REPOSITORY_OPEN_CROSS_FS) == 0)
487
+ !(flags & GIT_REPOSITORY_OPEN_CROSS_FS))
345
488
  break;
346
489
 
347
490
  if (S_ISDIR(st.st_mode)) {
348
- if (valid_repository_path(&path)) {
491
+ if (valid_repository_path(&path, &common_link)) {
349
492
  git_path_to_dir(&path);
350
- git_buf_set(repo_path, path.ptr, path.size);
493
+ git_buf_set(gitdir_path, path.ptr, path.size);
494
+
495
+ if (gitlink_path)
496
+ git_buf_attach(gitlink_path,
497
+ git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0);
498
+ if (commondir_path)
499
+ git_buf_swap(&common_link, commondir_path);
500
+
351
501
  break;
352
502
  }
353
503
  }
354
- else if (S_ISREG(st.st_mode)) {
355
- git_buf repo_link = GIT_BUF_INIT;
356
-
357
- if (!(error = read_gitfile(&repo_link, path.ptr))) {
358
- if (valid_repository_path(&repo_link))
359
- git_buf_swap(repo_path, &repo_link);
360
-
361
- git_buf_free(&repo_link);
504
+ else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
505
+ error = read_gitfile(&repo_link, path.ptr);
506
+ if (error < 0)
362
507
  break;
508
+ if (valid_repository_path(&repo_link, &common_link)) {
509
+ git_buf_swap(gitdir_path, &repo_link);
510
+
511
+ if (gitlink_path)
512
+ error = git_buf_put(gitlink_path, path.ptr, path.size);
513
+ if (commondir_path)
514
+ git_buf_swap(&common_link, commondir_path);
363
515
  }
364
- git_buf_free(&repo_link);
516
+ break;
365
517
  }
366
518
  }
367
519
 
368
- /* move up one directory level */
520
+ /* Move up one directory. If we're in_dot_git, we'll search the
521
+ * parent itself next. If we're !in_dot_git, we'll search .git
522
+ * in the parent directory next (added at the top of the loop). */
369
523
  if (git_path_dirname_r(&path, path.ptr) < 0) {
370
524
  error = -1;
371
525
  break;
372
526
  }
373
527
 
374
- if (try_with_dot_git) {
375
- /* if we tried original dir with and without .git AND either hit
376
- * directory ceiling or NO_SEARCH was requested, then be done.
377
- */
378
- if (path.ptr[ceiling_offset] == '\0' ||
379
- (flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0)
380
- break;
381
- /* otherwise look first for .git item */
382
- error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
383
- }
384
- try_with_dot_git = !try_with_dot_git;
528
+ /* Once we've checked the directory (and .git if applicable),
529
+ * find the ceiling for a search. */
530
+ if (min_iterations && (--min_iterations == 0))
531
+ ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
532
+
533
+ /* Check if we should stop searching here. */
534
+ if (min_iterations == 0
535
+ && (path.ptr[ceiling_offset] == 0
536
+ || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))
537
+ break;
385
538
  }
386
539
 
387
- if (!error && parent_path != NULL) {
388
- if (!git_buf_len(repo_path))
389
- git_buf_clear(parent_path);
540
+ if (!error && workdir_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
541
+ if (!git_buf_len(gitdir_path))
542
+ git_buf_clear(workdir_path);
390
543
  else {
391
- git_path_dirname_r(parent_path, path.ptr);
392
- git_path_to_dir(parent_path);
544
+ git_path_dirname_r(workdir_path, path.ptr);
545
+ git_path_to_dir(workdir_path);
393
546
  }
394
- if (git_buf_oom(parent_path))
547
+ if (git_buf_oom(workdir_path))
395
548
  return -1;
396
549
  }
397
550
 
398
- git_buf_free(&path);
399
-
400
- if (!git_buf_len(repo_path) && !error) {
401
- giterr_set(GITERR_REPOSITORY,
402
- "Could not find repository from '%s'", start_path);
551
+ /* If we didn't find the repository, and we don't have any other error
552
+ * to report, report that. */
553
+ if (!git_buf_len(gitdir_path) && !error) {
554
+ git_error_set(GIT_ERROR_REPOSITORY,
555
+ "could not find repository from '%s'", start_path);
403
556
  error = GIT_ENOTFOUND;
404
557
  }
405
558
 
559
+ git_buf_dispose(&path);
560
+ git_buf_dispose(&repo_link);
561
+ git_buf_dispose(&common_link);
406
562
  return error;
407
563
  }
408
564
 
@@ -411,32 +567,228 @@ int git_repository_open_bare(
411
567
  const char *bare_path)
412
568
  {
413
569
  int error;
414
- git_buf path = GIT_BUF_INIT;
570
+ git_buf path = GIT_BUF_INIT, common_path = GIT_BUF_INIT;
415
571
  git_repository *repo = NULL;
416
572
 
417
573
  if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0)
418
574
  return error;
419
575
 
420
- if (!valid_repository_path(&path)) {
421
- git_buf_free(&path);
422
- giterr_set(GITERR_REPOSITORY, "Path is not a repository: %s", bare_path);
576
+ if (!valid_repository_path(&path, &common_path)) {
577
+ git_buf_dispose(&path);
578
+ git_buf_dispose(&common_path);
579
+ git_error_set(GIT_ERROR_REPOSITORY, "path is not a repository: %s", bare_path);
423
580
  return GIT_ENOTFOUND;
424
581
  }
425
582
 
426
583
  repo = repository_alloc();
427
- GITERR_CHECK_ALLOC(repo);
584
+ GIT_ERROR_CHECK_ALLOC(repo);
428
585
 
429
- repo->path_repository = git_buf_detach(&path);
430
- GITERR_CHECK_ALLOC(repo->path_repository);
586
+ repo->gitdir = git_buf_detach(&path);
587
+ GIT_ERROR_CHECK_ALLOC(repo->gitdir);
588
+ repo->commondir = git_buf_detach(&common_path);
589
+ GIT_ERROR_CHECK_ALLOC(repo->commondir);
431
590
 
432
591
  /* of course we're bare! */
433
592
  repo->is_bare = 1;
593
+ repo->is_worktree = 0;
434
594
  repo->workdir = NULL;
435
595
 
436
596
  *repo_ptr = repo;
437
597
  return 0;
438
598
  }
439
599
 
600
+ static int _git_repository_open_ext_from_env(
601
+ git_repository **out,
602
+ const char *start_path)
603
+ {
604
+ git_repository *repo = NULL;
605
+ git_index *index = NULL;
606
+ git_odb *odb = NULL;
607
+ git_buf dir_buf = GIT_BUF_INIT;
608
+ git_buf ceiling_dirs_buf = GIT_BUF_INIT;
609
+ git_buf across_fs_buf = GIT_BUF_INIT;
610
+ git_buf index_file_buf = GIT_BUF_INIT;
611
+ git_buf namespace_buf = GIT_BUF_INIT;
612
+ git_buf object_dir_buf = GIT_BUF_INIT;
613
+ git_buf alts_buf = GIT_BUF_INIT;
614
+ git_buf work_tree_buf = GIT_BUF_INIT;
615
+ git_buf common_dir_buf = GIT_BUF_INIT;
616
+ const char *ceiling_dirs = NULL;
617
+ unsigned flags = 0;
618
+ int error;
619
+
620
+ if (!start_path) {
621
+ error = git__getenv(&dir_buf, "GIT_DIR");
622
+ if (error == GIT_ENOTFOUND) {
623
+ git_error_clear();
624
+ start_path = ".";
625
+ } else if (error < 0)
626
+ goto error;
627
+ else {
628
+ start_path = git_buf_cstr(&dir_buf);
629
+ flags |= GIT_REPOSITORY_OPEN_NO_SEARCH;
630
+ flags |= GIT_REPOSITORY_OPEN_NO_DOTGIT;
631
+ }
632
+ }
633
+
634
+ error = git__getenv(&ceiling_dirs_buf, "GIT_CEILING_DIRECTORIES");
635
+ if (error == GIT_ENOTFOUND)
636
+ git_error_clear();
637
+ else if (error < 0)
638
+ goto error;
639
+ else
640
+ ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
641
+
642
+ error = git__getenv(&across_fs_buf, "GIT_DISCOVERY_ACROSS_FILESYSTEM");
643
+ if (error == GIT_ENOTFOUND)
644
+ git_error_clear();
645
+ else if (error < 0)
646
+ goto error;
647
+ else {
648
+ int across_fs = 0;
649
+ error = git_config_parse_bool(&across_fs, git_buf_cstr(&across_fs_buf));
650
+ if (error < 0)
651
+ goto error;
652
+ if (across_fs)
653
+ flags |= GIT_REPOSITORY_OPEN_CROSS_FS;
654
+ }
655
+
656
+ error = git__getenv(&index_file_buf, "GIT_INDEX_FILE");
657
+ if (error == GIT_ENOTFOUND)
658
+ git_error_clear();
659
+ else if (error < 0)
660
+ goto error;
661
+ else {
662
+ error = git_index_open(&index, git_buf_cstr(&index_file_buf));
663
+ if (error < 0)
664
+ goto error;
665
+ }
666
+
667
+ error = git__getenv(&namespace_buf, "GIT_NAMESPACE");
668
+ if (error == GIT_ENOTFOUND)
669
+ git_error_clear();
670
+ else if (error < 0)
671
+ goto error;
672
+
673
+ error = git__getenv(&object_dir_buf, "GIT_OBJECT_DIRECTORY");
674
+ if (error == GIT_ENOTFOUND)
675
+ git_error_clear();
676
+ else if (error < 0)
677
+ goto error;
678
+ else {
679
+ error = git_odb_open(&odb, git_buf_cstr(&object_dir_buf));
680
+ if (error < 0)
681
+ goto error;
682
+ }
683
+
684
+ error = git__getenv(&work_tree_buf, "GIT_WORK_TREE");
685
+ if (error == GIT_ENOTFOUND)
686
+ git_error_clear();
687
+ else if (error < 0)
688
+ goto error;
689
+ else {
690
+ git_error_set(GIT_ERROR_INVALID, "GIT_WORK_TREE unimplemented");
691
+ error = GIT_ERROR;
692
+ goto error;
693
+ }
694
+
695
+ error = git__getenv(&work_tree_buf, "GIT_COMMON_DIR");
696
+ if (error == GIT_ENOTFOUND)
697
+ git_error_clear();
698
+ else if (error < 0)
699
+ goto error;
700
+ else {
701
+ git_error_set(GIT_ERROR_INVALID, "GIT_COMMON_DIR unimplemented");
702
+ error = GIT_ERROR;
703
+ goto error;
704
+ }
705
+
706
+ error = git_repository_open_ext(&repo, start_path, flags, ceiling_dirs);
707
+ if (error < 0)
708
+ goto error;
709
+
710
+ if (odb)
711
+ git_repository_set_odb(repo, odb);
712
+
713
+ error = git__getenv(&alts_buf, "GIT_ALTERNATE_OBJECT_DIRECTORIES");
714
+ if (error == GIT_ENOTFOUND) {
715
+ git_error_clear();
716
+ error = 0;
717
+ } else if (error < 0)
718
+ goto error;
719
+ else {
720
+ const char *end;
721
+ char *alt, *sep;
722
+ if (!odb) {
723
+ error = git_repository_odb(&odb, repo);
724
+ if (error < 0)
725
+ goto error;
726
+ }
727
+
728
+ end = git_buf_cstr(&alts_buf) + git_buf_len(&alts_buf);
729
+ for (sep = alt = alts_buf.ptr; sep != end; alt = sep+1) {
730
+ for (sep = alt; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++)
731
+ ;
732
+ if (*sep)
733
+ *sep = '\0';
734
+ error = git_odb_add_disk_alternate(odb, alt);
735
+ if (error < 0)
736
+ goto error;
737
+ }
738
+ }
739
+
740
+ if (git_buf_len(&namespace_buf)) {
741
+ error = git_repository_set_namespace(repo, git_buf_cstr(&namespace_buf));
742
+ if (error < 0)
743
+ goto error;
744
+ }
745
+
746
+ git_repository_set_index(repo, index);
747
+
748
+ if (out) {
749
+ *out = repo;
750
+ goto success;
751
+ }
752
+ error:
753
+ git_repository_free(repo);
754
+ success:
755
+ git_odb_free(odb);
756
+ git_index_free(index);
757
+ git_buf_dispose(&common_dir_buf);
758
+ git_buf_dispose(&work_tree_buf);
759
+ git_buf_dispose(&alts_buf);
760
+ git_buf_dispose(&object_dir_buf);
761
+ git_buf_dispose(&namespace_buf);
762
+ git_buf_dispose(&index_file_buf);
763
+ git_buf_dispose(&across_fs_buf);
764
+ git_buf_dispose(&ceiling_dirs_buf);
765
+ git_buf_dispose(&dir_buf);
766
+ return error;
767
+ }
768
+
769
+ static int repo_is_worktree(unsigned *out, const git_repository *repo)
770
+ {
771
+ git_buf gitdir_link = GIT_BUF_INIT;
772
+ int error;
773
+
774
+ /* Worktrees cannot have the same commondir and gitdir */
775
+ if (repo->commondir && repo->gitdir
776
+ && !strcmp(repo->commondir, repo->gitdir)) {
777
+ *out = 0;
778
+ return 0;
779
+ }
780
+
781
+ if ((error = git_buf_joinpath(&gitdir_link, repo->gitdir, "gitdir")) < 0)
782
+ return -1;
783
+
784
+ /* A 'gitdir' file inside a git directory is currently
785
+ * only used when the repository is a working tree. */
786
+ *out = !!git_path_exists(gitdir_link.ptr);
787
+
788
+ git_buf_dispose(&gitdir_link);
789
+ return error;
790
+ }
791
+
440
792
  int git_repository_open_ext(
441
793
  git_repository **repo_ptr,
442
794
  const char *start_path,
@@ -444,32 +796,76 @@ int git_repository_open_ext(
444
796
  const char *ceiling_dirs)
445
797
  {
446
798
  int error;
447
- git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT;
799
+ unsigned is_worktree;
800
+ git_buf gitdir = GIT_BUF_INIT, workdir = GIT_BUF_INIT,
801
+ gitlink = GIT_BUF_INIT, commondir = GIT_BUF_INIT;
448
802
  git_repository *repo;
803
+ git_config *config = NULL;
804
+
805
+ if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
806
+ return _git_repository_open_ext_from_env(repo_ptr, start_path);
449
807
 
450
808
  if (repo_ptr)
451
809
  *repo_ptr = NULL;
452
810
 
453
- error = find_repo(&path, &parent, start_path, flags, ceiling_dirs);
811
+ error = find_repo(
812
+ &gitdir, &workdir, &gitlink, &commondir, start_path, flags, ceiling_dirs);
813
+
454
814
  if (error < 0 || !repo_ptr)
455
815
  return error;
456
816
 
457
817
  repo = repository_alloc();
458
- GITERR_CHECK_ALLOC(repo);
818
+ GIT_ERROR_CHECK_ALLOC(repo);
459
819
 
460
- repo->path_repository = git_buf_detach(&path);
461
- GITERR_CHECK_ALLOC(repo->path_repository);
820
+ repo->gitdir = git_buf_detach(&gitdir);
821
+ GIT_ERROR_CHECK_ALLOC(repo->gitdir);
462
822
 
463
- if ((error = load_config_data(repo)) < 0 ||
464
- (error = load_workdir(repo, &parent)) < 0)
465
- {
466
- git_repository_free(repo);
467
- return error;
823
+ if (gitlink.size) {
824
+ repo->gitlink = git_buf_detach(&gitlink);
825
+ GIT_ERROR_CHECK_ALLOC(repo->gitlink);
826
+ }
827
+ if (commondir.size) {
828
+ repo->commondir = git_buf_detach(&commondir);
829
+ GIT_ERROR_CHECK_ALLOC(repo->commondir);
468
830
  }
469
831
 
470
- git_buf_free(&parent);
471
- *repo_ptr = repo;
472
- return 0;
832
+ if ((error = repo_is_worktree(&is_worktree, repo)) < 0)
833
+ goto cleanup;
834
+ repo->is_worktree = is_worktree;
835
+
836
+ /*
837
+ * We'd like to have the config, but git doesn't particularly
838
+ * care if it's not there, so we need to deal with that.
839
+ */
840
+
841
+ error = git_repository_config_snapshot(&config, repo);
842
+ if (error < 0 && error != GIT_ENOTFOUND)
843
+ goto cleanup;
844
+
845
+ if (config && (error = check_repositoryformatversion(config)) < 0)
846
+ goto cleanup;
847
+
848
+ if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
849
+ repo->is_bare = 1;
850
+ else {
851
+
852
+ if (config &&
853
+ ((error = load_config_data(repo, config)) < 0 ||
854
+ (error = load_workdir(repo, config, &workdir)) < 0))
855
+ goto cleanup;
856
+ }
857
+
858
+ cleanup:
859
+ git_buf_dispose(&gitdir);
860
+ git_buf_dispose(&workdir);
861
+ git_config_free(config);
862
+
863
+ if (error < 0)
864
+ git_repository_free(repo);
865
+ else
866
+ *repo_ptr = repo;
867
+
868
+ return error;
473
869
  }
474
870
 
475
871
  int git_repository_open(git_repository **repo_out, const char *path)
@@ -478,12 +874,42 @@ int git_repository_open(git_repository **repo_out, const char *path)
478
874
  repo_out, path, GIT_REPOSITORY_OPEN_NO_SEARCH, NULL);
479
875
  }
480
876
 
877
+ int git_repository_open_from_worktree(git_repository **repo_out, git_worktree *wt)
878
+ {
879
+ git_buf path = GIT_BUF_INIT;
880
+ git_repository *repo = NULL;
881
+ int len, err;
882
+
883
+ assert(repo_out && wt);
884
+
885
+ *repo_out = NULL;
886
+ len = strlen(wt->gitlink_path);
887
+
888
+ if (len <= 4 || strcasecmp(wt->gitlink_path + len - 4, ".git")) {
889
+ err = -1;
890
+ goto out;
891
+ }
892
+
893
+ if ((err = git_buf_set(&path, wt->gitlink_path, len - 4)) < 0)
894
+ goto out;
895
+
896
+ if ((err = git_repository_open(&repo, path.ptr)) < 0)
897
+ goto out;
898
+
899
+ *repo_out = repo;
900
+
901
+ out:
902
+ git_buf_dispose(&path);
903
+
904
+ return err;
905
+ }
906
+
481
907
  int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb)
482
908
  {
483
909
  git_repository *repo;
484
910
 
485
911
  repo = repository_alloc();
486
- GITERR_CHECK_ALLOC(repo);
912
+ GIT_ERROR_CHECK_ALLOC(repo);
487
913
 
488
914
  git_repository_set_odb(repo, odb);
489
915
  *repo_out = repo;
@@ -492,34 +918,18 @@ int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb)
492
918
  }
493
919
 
494
920
  int git_repository_discover(
495
- char *repository_path,
496
- size_t size,
921
+ git_buf *out,
497
922
  const char *start_path,
498
923
  int across_fs,
499
924
  const char *ceiling_dirs)
500
925
  {
501
- git_buf path = GIT_BUF_INIT;
502
926
  uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
503
- int error;
504
-
505
- assert(start_path && repository_path && size > 0);
506
927
 
507
- *repository_path = '\0';
928
+ assert(start_path);
508
929
 
509
- if ((error = find_repo(&path, NULL, start_path, flags, ceiling_dirs)) < 0)
510
- return error != GIT_ENOTFOUND ? -1 : error;
511
-
512
- if (size < (size_t)(path.size + 1)) {
513
- giterr_set(GITERR_REPOSITORY,
514
- "The given buffer is too small to store the discovered path");
515
- git_buf_free(&path);
516
- return -1;
517
- }
930
+ git_buf_sanitize(out);
518
931
 
519
- /* success: we discovered a repository */
520
- git_buf_copy_cstr(repository_path, size, &path);
521
- git_buf_free(&path);
522
- return 0;
932
+ return find_repo(out, NULL, NULL, NULL, start_path, flags, ceiling_dirs);
523
933
  }
524
934
 
525
935
  static int load_config(
@@ -527,54 +937,59 @@ static int load_config(
527
937
  git_repository *repo,
528
938
  const char *global_config_path,
529
939
  const char *xdg_config_path,
530
- const char *system_config_path)
940
+ const char *system_config_path,
941
+ const char *programdata_path)
531
942
  {
532
943
  int error;
533
944
  git_buf config_path = GIT_BUF_INIT;
534
945
  git_config *cfg = NULL;
535
946
 
536
- assert(repo && out);
947
+ assert(out);
537
948
 
538
949
  if ((error = git_config_new(&cfg)) < 0)
539
950
  return error;
540
951
 
541
- error = git_buf_joinpath(
542
- &config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
543
- if (error < 0)
544
- goto on_error;
952
+ if (repo) {
953
+ if ((error = git_repository_item_path(&config_path, repo, GIT_REPOSITORY_ITEM_CONFIG)) == 0)
954
+ error = git_config_add_file_ondisk(cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, repo, 0);
545
955
 
546
- if ((error = git_config_add_file_ondisk(
547
- cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0 &&
548
- error != GIT_ENOTFOUND)
549
- goto on_error;
956
+ if (error && error != GIT_ENOTFOUND)
957
+ goto on_error;
550
958
 
551
- git_buf_free(&config_path);
959
+ git_buf_dispose(&config_path);
960
+ }
552
961
 
553
962
  if (global_config_path != NULL &&
554
963
  (error = git_config_add_file_ondisk(
555
- cfg, global_config_path, GIT_CONFIG_LEVEL_GLOBAL, 0)) < 0 &&
964
+ cfg, global_config_path, GIT_CONFIG_LEVEL_GLOBAL, repo, 0)) < 0 &&
556
965
  error != GIT_ENOTFOUND)
557
966
  goto on_error;
558
967
 
559
968
  if (xdg_config_path != NULL &&
560
969
  (error = git_config_add_file_ondisk(
561
- cfg, xdg_config_path, GIT_CONFIG_LEVEL_XDG, 0)) < 0 &&
970
+ cfg, xdg_config_path, GIT_CONFIG_LEVEL_XDG, repo, 0)) < 0 &&
562
971
  error != GIT_ENOTFOUND)
563
972
  goto on_error;
564
973
 
565
974
  if (system_config_path != NULL &&
566
975
  (error = git_config_add_file_ondisk(
567
- cfg, system_config_path, GIT_CONFIG_LEVEL_SYSTEM, 0)) < 0 &&
976
+ cfg, system_config_path, GIT_CONFIG_LEVEL_SYSTEM, repo, 0)) < 0 &&
977
+ error != GIT_ENOTFOUND)
978
+ goto on_error;
979
+
980
+ if (programdata_path != NULL &&
981
+ (error = git_config_add_file_ondisk(
982
+ cfg, programdata_path, GIT_CONFIG_LEVEL_PROGRAMDATA, repo, 0)) < 0 &&
568
983
  error != GIT_ENOTFOUND)
569
984
  goto on_error;
570
985
 
571
- giterr_clear(); /* clear any lingering ENOTFOUND errors */
986
+ git_error_clear(); /* clear any lingering ENOTFOUND errors */
572
987
 
573
988
  *out = cfg;
574
989
  return 0;
575
990
 
576
991
  on_error:
577
- git_buf_free(&config_path);
992
+ git_buf_dispose(&config_path);
578
993
  git_config_free(cfg);
579
994
  *out = NULL;
580
995
  return error;
@@ -593,11 +1008,13 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
593
1008
  git_buf global_buf = GIT_BUF_INIT;
594
1009
  git_buf xdg_buf = GIT_BUF_INIT;
595
1010
  git_buf system_buf = GIT_BUF_INIT;
1011
+ git_buf programdata_buf = GIT_BUF_INIT;
596
1012
  git_config *config;
597
1013
 
598
- git_config_find_global_r(&global_buf);
599
- git_config_find_xdg_r(&xdg_buf);
600
- git_config_find_system_r(&system_buf);
1014
+ git_config_find_global(&global_buf);
1015
+ git_config_find_xdg(&xdg_buf);
1016
+ git_config_find_system(&system_buf);
1017
+ git_config_find_programdata(&programdata_buf);
601
1018
 
602
1019
  /* If there is no global file, open a backend for it anyway */
603
1020
  if (git_buf_len(&global_buf) == 0)
@@ -607,7 +1024,8 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
607
1024
  &config, repo,
608
1025
  path_unless_empty(&global_buf),
609
1026
  path_unless_empty(&xdg_buf),
610
- path_unless_empty(&system_buf));
1027
+ path_unless_empty(&system_buf),
1028
+ path_unless_empty(&programdata_buf));
611
1029
  if (!error) {
612
1030
  GIT_REFCOUNT_OWN(config, repo);
613
1031
 
@@ -618,9 +1036,10 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
618
1036
  }
619
1037
  }
620
1038
 
621
- git_buf_free(&global_buf);
622
- git_buf_free(&xdg_buf);
623
- git_buf_free(&system_buf);
1039
+ git_buf_dispose(&global_buf);
1040
+ git_buf_dispose(&xdg_buf);
1041
+ git_buf_dispose(&system_buf);
1042
+ git_buf_dispose(&programdata_buf);
624
1043
  }
625
1044
 
626
1045
  *out = repo->_config;
@@ -636,6 +1055,17 @@ int git_repository_config(git_config **out, git_repository *repo)
636
1055
  return 0;
637
1056
  }
638
1057
 
1058
+ int git_repository_config_snapshot(git_config **out, git_repository *repo)
1059
+ {
1060
+ int error;
1061
+ git_config *weak;
1062
+
1063
+ if ((error = git_repository_config__weakptr(&weak, repo)) < 0)
1064
+ return error;
1065
+
1066
+ return git_config_snapshot(out, weak);
1067
+ }
1068
+
639
1069
  void git_repository_set_config(git_repository *repo, git_config *config)
640
1070
  {
641
1071
  assert(repo && config);
@@ -652,20 +1082,26 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
652
1082
  git_buf odb_path = GIT_BUF_INIT;
653
1083
  git_odb *odb;
654
1084
 
655
- git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR);
1085
+ if ((error = git_repository_item_path(&odb_path, repo,
1086
+ GIT_REPOSITORY_ITEM_OBJECTS)) < 0 ||
1087
+ (error = git_odb_new(&odb)) < 0)
1088
+ return error;
1089
+
1090
+ GIT_REFCOUNT_OWN(odb, repo);
656
1091
 
657
- error = git_odb_open(&odb, odb_path.ptr);
658
- if (!error) {
659
- GIT_REFCOUNT_OWN(odb, repo);
1092
+ if ((error = git_odb__set_caps(odb, GIT_ODB_CAP_FROM_OWNER)) < 0 ||
1093
+ (error = git_odb__add_default_backends(odb, odb_path.ptr, 0, 0)) < 0) {
1094
+ git_odb_free(odb);
1095
+ return error;
1096
+ }
660
1097
 
661
- odb = git__compare_and_swap(&repo->_odb, NULL, odb);
662
- if (odb != NULL) {
663
- GIT_REFCOUNT_OWN(odb, NULL);
664
- git_odb_free(odb);
665
- }
1098
+ odb = git__compare_and_swap(&repo->_odb, NULL, odb);
1099
+ if (odb != NULL) {
1100
+ GIT_REFCOUNT_OWN(odb, NULL);
1101
+ git_odb_free(odb);
666
1102
  }
667
1103
 
668
- git_buf_free(&odb_path);
1104
+ git_buf_dispose(&odb_path);
669
1105
  }
670
1106
 
671
1107
  *out = repo->_odb;
@@ -737,7 +1173,8 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
737
1173
  git_buf index_path = GIT_BUF_INIT;
738
1174
  git_index *index;
739
1175
 
740
- git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE);
1176
+ if ((error = git_buf_joinpath(&index_path, repo->gitdir, GIT_INDEX_FILE)) < 0)
1177
+ return error;
741
1178
 
742
1179
  error = git_index_open(&index, index_path.ptr);
743
1180
  if (!error) {
@@ -749,10 +1186,11 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
749
1186
  git_index_free(index);
750
1187
  }
751
1188
 
752
- error = git_index_set_caps(repo->_index, GIT_INDEXCAP_FROM_OWNER);
1189
+ error = git_index_set_caps(repo->_index,
1190
+ GIT_INDEX_CAPABILITY_FROM_OWNER);
753
1191
  }
754
1192
 
755
- git_buf_free(&index_path);
1193
+ git_buf_dispose(&index_path);
756
1194
  }
757
1195
 
758
1196
  *out = repo->_index;
@@ -770,7 +1208,7 @@ int git_repository_index(git_index **out, git_repository *repo)
770
1208
 
771
1209
  void git_repository_set_index(git_repository *repo, git_index *index)
772
1210
  {
773
- assert(repo && index);
1211
+ assert(repo);
774
1212
  set_index(repo, index);
775
1213
  }
776
1214
 
@@ -791,31 +1229,138 @@ const char *git_repository_get_namespace(git_repository *repo)
791
1229
  return repo->namespace;
792
1230
  }
793
1231
 
794
- static int check_repositoryformatversion(git_config *config)
1232
+ #ifdef GIT_WIN32
1233
+ static int reserved_names_add8dot3(git_repository *repo, const char *path)
795
1234
  {
796
- int version;
1235
+ char *name = git_win32_path_8dot3_name(path);
1236
+ const char *def = GIT_DIR_SHORTNAME;
1237
+ const char *def_dot_git = DOT_GIT;
1238
+ size_t name_len, def_len = CONST_STRLEN(GIT_DIR_SHORTNAME);
1239
+ size_t def_dot_git_len = CONST_STRLEN(DOT_GIT);
1240
+ git_buf *buf;
797
1241
 
798
- if (git_config_get_int32(&version, config, "core.repositoryformatversion") < 0)
799
- return -1;
1242
+ if (!name)
1243
+ return 0;
800
1244
 
801
- if (GIT_REPO_VERSION < version) {
802
- giterr_set(GITERR_REPOSITORY,
803
- "Unsupported repository version %d. Only versions up to %d are supported.",
804
- version, GIT_REPO_VERSION);
805
- return -1;
1245
+ name_len = strlen(name);
1246
+
1247
+ if ((name_len == def_len && memcmp(name, def, def_len) == 0) ||
1248
+ (name_len == def_dot_git_len && memcmp(name, def_dot_git, def_dot_git_len) == 0)) {
1249
+ git__free(name);
1250
+ return 0;
806
1251
  }
807
1252
 
808
- return 0;
1253
+ if ((buf = git_array_alloc(repo->reserved_names)) == NULL)
1254
+ return -1;
1255
+
1256
+ git_buf_attach(buf, name, name_len);
1257
+ return true;
809
1258
  }
810
1259
 
811
- static int repo_init_create_head(const char *git_dir, const char *ref_name)
1260
+ bool git_repository__reserved_names(
1261
+ git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs)
812
1262
  {
813
- git_buf ref_path = GIT_BUF_INIT;
814
- git_filebuf ref = GIT_FILEBUF_INIT;
815
- const char *fmt;
1263
+ GIT_UNUSED(include_ntfs);
1264
+
1265
+ if (repo->reserved_names.size == 0) {
1266
+ git_buf *buf;
1267
+ size_t i;
1268
+
1269
+ /* Add the static defaults */
1270
+ for (i = 0; i < git_repository__reserved_names_win32_len; i++) {
1271
+ if ((buf = git_array_alloc(repo->reserved_names)) == NULL)
1272
+ goto on_error;
1273
+
1274
+ buf->ptr = git_repository__reserved_names_win32[i].ptr;
1275
+ buf->size = git_repository__reserved_names_win32[i].size;
1276
+ }
1277
+
1278
+ /* Try to add any repo-specific reserved names - the gitlink file
1279
+ * within a submodule or the repository (if the repository directory
1280
+ * is beneath the workdir). These are typically `.git`, but should
1281
+ * be protected in case they are not. Note, repo and workdir paths
1282
+ * are always prettified to end in `/`, so a prefixcmp is safe.
1283
+ */
1284
+ if (!repo->is_bare) {
1285
+ int (*prefixcmp)(const char *, const char *);
1286
+ int error, ignorecase;
1287
+
1288
+ error = git_repository__cvar(
1289
+ &ignorecase, repo, GIT_CVAR_IGNORECASE);
1290
+ prefixcmp = (error || ignorecase) ? git__prefixcmp_icase :
1291
+ git__prefixcmp;
1292
+
1293
+ if (repo->gitlink &&
1294
+ reserved_names_add8dot3(repo, repo->gitlink) < 0)
1295
+ goto on_error;
1296
+
1297
+ if (repo->gitdir &&
1298
+ prefixcmp(repo->gitdir, repo->workdir) == 0 &&
1299
+ reserved_names_add8dot3(repo, repo->gitdir) < 0)
1300
+ goto on_error;
1301
+ }
1302
+ }
1303
+
1304
+ *out = repo->reserved_names.ptr;
1305
+ *outlen = repo->reserved_names.size;
1306
+
1307
+ return true;
1308
+
1309
+ /* Always give good defaults, even on OOM */
1310
+ on_error:
1311
+ *out = git_repository__reserved_names_win32;
1312
+ *outlen = git_repository__reserved_names_win32_len;
1313
+
1314
+ return false;
1315
+ }
1316
+ #else
1317
+ bool git_repository__reserved_names(
1318
+ git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs)
1319
+ {
1320
+ GIT_UNUSED(repo);
1321
+
1322
+ if (include_ntfs) {
1323
+ *out = git_repository__reserved_names_win32;
1324
+ *outlen = git_repository__reserved_names_win32_len;
1325
+ } else {
1326
+ *out = git_repository__reserved_names_posix;
1327
+ *outlen = git_repository__reserved_names_posix_len;
1328
+ }
1329
+
1330
+ return true;
1331
+ }
1332
+ #endif
1333
+
1334
+ static int check_repositoryformatversion(git_config *config)
1335
+ {
1336
+ int version, error;
1337
+
1338
+ error = git_config_get_int32(&version, config, "core.repositoryformatversion");
1339
+ /* git ignores this if the config variable isn't there */
1340
+ if (error == GIT_ENOTFOUND)
1341
+ return 0;
1342
+
1343
+ if (error < 0)
1344
+ return -1;
1345
+
1346
+ if (GIT_REPO_VERSION < version) {
1347
+ git_error_set(GIT_ERROR_REPOSITORY,
1348
+ "unsupported repository version %d. Only versions up to %d are supported.",
1349
+ version, GIT_REPO_VERSION);
1350
+ return -1;
1351
+ }
1352
+
1353
+ return 0;
1354
+ }
1355
+
1356
+ int git_repository_create_head(const char *git_dir, const char *ref_name)
1357
+ {
1358
+ git_buf ref_path = GIT_BUF_INIT;
1359
+ git_filebuf ref = GIT_FILEBUF_INIT;
1360
+ const char *fmt;
816
1361
 
817
1362
  if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
818
- git_filebuf_open(&ref, ref_path.ptr, 0) < 0)
1363
+ git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE) < 0)
819
1364
  goto fail;
820
1365
 
821
1366
  if (!ref_name)
@@ -827,14 +1372,14 @@ static int repo_init_create_head(const char *git_dir, const char *ref_name)
827
1372
  fmt = "ref: " GIT_REFS_HEADS_DIR "%s\n";
828
1373
 
829
1374
  if (git_filebuf_printf(&ref, fmt, ref_name) < 0 ||
830
- git_filebuf_commit(&ref, GIT_REFS_FILE_MODE) < 0)
1375
+ git_filebuf_commit(&ref) < 0)
831
1376
  goto fail;
832
1377
 
833
- git_buf_free(&ref_path);
1378
+ git_buf_dispose(&ref_path);
834
1379
  return 0;
835
1380
 
836
1381
  fail:
837
- git_buf_free(&ref_path);
1382
+ git_buf_dispose(&ref_path);
838
1383
  git_filebuf_cleanup(&ref);
839
1384
  return -1;
840
1385
  }
@@ -842,10 +1387,6 @@ fail:
842
1387
  static bool is_chmod_supported(const char *file_path)
843
1388
  {
844
1389
  struct stat st1, st2;
845
- static int _is_supported = -1;
846
-
847
- if (_is_supported > -1)
848
- return _is_supported;
849
1390
 
850
1391
  if (p_stat(file_path, &st1) < 0)
851
1392
  return false;
@@ -856,52 +1397,76 @@ static bool is_chmod_supported(const char *file_path)
856
1397
  if (p_stat(file_path, &st2) < 0)
857
1398
  return false;
858
1399
 
859
- _is_supported = (st1.st_mode != st2.st_mode);
860
-
861
- return _is_supported;
1400
+ return (st1.st_mode != st2.st_mode);
862
1401
  }
863
1402
 
864
1403
  static bool is_filesystem_case_insensitive(const char *gitdir_path)
865
1404
  {
866
1405
  git_buf path = GIT_BUF_INIT;
867
- static int _is_insensitive = -1;
868
-
869
- if (_is_insensitive > -1)
870
- return _is_insensitive;
1406
+ int is_insensitive = -1;
871
1407
 
872
- if (git_buf_joinpath(&path, gitdir_path, "CoNfIg") < 0)
873
- goto cleanup;
874
-
875
- _is_insensitive = git_path_exists(git_buf_cstr(&path));
1408
+ if (!git_buf_joinpath(&path, gitdir_path, "CoNfIg"))
1409
+ is_insensitive = git_path_exists(git_buf_cstr(&path));
876
1410
 
877
- cleanup:
878
- git_buf_free(&path);
879
- return _is_insensitive;
1411
+ git_buf_dispose(&path);
1412
+ return is_insensitive;
880
1413
  }
881
1414
 
882
1415
  static bool are_symlinks_supported(const char *wd_path)
883
1416
  {
1417
+ git_config *config = NULL;
1418
+ git_buf global_buf = GIT_BUF_INIT;
1419
+ git_buf xdg_buf = GIT_BUF_INIT;
1420
+ git_buf system_buf = GIT_BUF_INIT;
1421
+ git_buf programdata_buf = GIT_BUF_INIT;
884
1422
  git_buf path = GIT_BUF_INIT;
885
1423
  int fd;
886
1424
  struct stat st;
887
- static int _symlinks_supported = -1;
1425
+ int symlinks = 0;
1426
+
1427
+ /*
1428
+ * To emulate Git for Windows, symlinks on Windows must be explicitly
1429
+ * opted-in. We examine the system configuration for a core.symlinks
1430
+ * set to true. If found, we then examine the filesystem to see if
1431
+ * symlinks are _actually_ supported by the current user. If that is
1432
+ * _not_ set, then we do not test or enable symlink support.
1433
+ */
1434
+ #ifdef GIT_WIN32
1435
+ git_config_find_global(&global_buf);
1436
+ git_config_find_xdg(&xdg_buf);
1437
+ git_config_find_system(&system_buf);
1438
+ git_config_find_programdata(&programdata_buf);
1439
+
1440
+ if (load_config(&config, NULL,
1441
+ path_unless_empty(&global_buf),
1442
+ path_unless_empty(&xdg_buf),
1443
+ path_unless_empty(&system_buf),
1444
+ path_unless_empty(&programdata_buf)) < 0)
1445
+ goto done;
1446
+
1447
+ if (git_config_get_bool(&symlinks, config, "core.symlinks") < 0 || !symlinks)
1448
+ goto done;
1449
+ #endif
888
1450
 
889
- if (_symlinks_supported > -1)
890
- return _symlinks_supported;
1451
+ if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 ||
1452
+ p_close(fd) < 0 ||
1453
+ p_unlink(path.ptr) < 0 ||
1454
+ p_symlink("testing", path.ptr) < 0 ||
1455
+ p_lstat(path.ptr, &st) < 0)
1456
+ goto done;
891
1457
 
892
- if ((fd = git_futils_mktmp(&path, wd_path)) < 0 ||
893
- p_close(fd) < 0 ||
894
- p_unlink(path.ptr) < 0 ||
895
- p_symlink("testing", path.ptr) < 0 ||
896
- p_lstat(path.ptr, &st) < 0)
897
- _symlinks_supported = false;
898
- else
899
- _symlinks_supported = (S_ISLNK(st.st_mode) != 0);
1458
+ symlinks = (S_ISLNK(st.st_mode) != 0);
900
1459
 
901
1460
  (void)p_unlink(path.ptr);
902
- git_buf_free(&path);
903
1461
 
904
- return _symlinks_supported;
1462
+ done:
1463
+ git_buf_dispose(&global_buf);
1464
+ git_buf_dispose(&xdg_buf);
1465
+ git_buf_dispose(&system_buf);
1466
+ git_buf_dispose(&programdata_buf);
1467
+ git_buf_dispose(&path);
1468
+ git_config_free(config);
1469
+ return symlinks != 0;
905
1470
  }
906
1471
 
907
1472
  static int create_empty_file(const char *path, mode_t mode)
@@ -909,90 +1474,194 @@ static int create_empty_file(const char *path, mode_t mode)
909
1474
  int fd;
910
1475
 
911
1476
  if ((fd = p_creat(path, mode)) < 0) {
912
- giterr_set(GITERR_OS, "Error while creating '%s'", path);
1477
+ git_error_set(GIT_ERROR_OS, "error while creating '%s'", path);
913
1478
  return -1;
914
1479
  }
915
1480
 
916
1481
  if (p_close(fd) < 0) {
917
- giterr_set(GITERR_OS, "Error while closing '%s'", path);
1482
+ git_error_set(GIT_ERROR_OS, "error while closing '%s'", path);
918
1483
  return -1;
919
1484
  }
920
1485
 
921
1486
  return 0;
922
1487
  }
923
1488
 
924
- static int repo_init_config(
1489
+ static int repo_local_config(
1490
+ git_config **out,
1491
+ git_buf *config_dir,
1492
+ git_repository *repo,
1493
+ const char *repo_dir)
1494
+ {
1495
+ int error = 0;
1496
+ git_config *parent;
1497
+ const char *cfg_path;
1498
+
1499
+ if (git_buf_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
1500
+ return -1;
1501
+ cfg_path = git_buf_cstr(config_dir);
1502
+
1503
+ /* make LOCAL config if missing */
1504
+ if (!git_path_isfile(cfg_path) &&
1505
+ (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0)
1506
+ return error;
1507
+
1508
+ /* if no repo, just open that file directly */
1509
+ if (!repo)
1510
+ return git_config_open_ondisk(out, cfg_path);
1511
+
1512
+ /* otherwise, open parent config and get that level */
1513
+ if ((error = git_repository_config__weakptr(&parent, repo)) < 0)
1514
+ return error;
1515
+
1516
+ if (git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL) < 0) {
1517
+ git_error_clear();
1518
+
1519
+ if (!(error = git_config_add_file_ondisk(
1520
+ parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, repo, false)))
1521
+ error = git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL);
1522
+ }
1523
+
1524
+ git_config_free(parent);
1525
+
1526
+ return error;
1527
+ }
1528
+
1529
+ static int repo_init_fs_configs(
1530
+ git_config *cfg,
1531
+ const char *cfg_path,
925
1532
  const char *repo_dir,
926
1533
  const char *work_dir,
927
- git_repository_init_options *opts)
1534
+ bool update_ignorecase)
928
1535
  {
929
1536
  int error = 0;
930
- git_buf cfg_path = GIT_BUF_INIT;
931
- git_config *config = NULL;
932
1537
 
933
- #define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\
934
- if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \
935
- goto cleanup; } while (0)
1538
+ if (!work_dir)
1539
+ work_dir = repo_dir;
936
1540
 
937
- if (git_buf_joinpath(&cfg_path, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
938
- return -1;
1541
+ if ((error = git_config_set_bool(
1542
+ cfg, "core.filemode", is_chmod_supported(cfg_path))) < 0)
1543
+ return error;
939
1544
 
940
- if (!git_path_isfile(git_buf_cstr(&cfg_path)) &&
941
- create_empty_file(git_buf_cstr(&cfg_path), GIT_CONFIG_FILE_MODE) < 0) {
942
- git_buf_free(&cfg_path);
943
- return -1;
944
- }
1545
+ if (!are_symlinks_supported(work_dir)) {
1546
+ if ((error = git_config_set_bool(cfg, "core.symlinks", false)) < 0)
1547
+ return error;
1548
+ } else if (git_config_delete_entry(cfg, "core.symlinks") < 0)
1549
+ git_error_clear();
945
1550
 
946
- if (git_config_open_ondisk(&config, git_buf_cstr(&cfg_path)) < 0) {
947
- git_buf_free(&cfg_path);
948
- return -1;
1551
+ if (update_ignorecase) {
1552
+ if (is_filesystem_case_insensitive(repo_dir)) {
1553
+ if ((error = git_config_set_bool(cfg, "core.ignorecase", true)) < 0)
1554
+ return error;
1555
+ } else if (git_config_delete_entry(cfg, "core.ignorecase") < 0)
1556
+ git_error_clear();
949
1557
  }
950
1558
 
951
- if ((opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0 &&
952
- (error = check_repositoryformatversion(config)) < 0)
1559
+ #ifdef GIT_USE_ICONV
1560
+ if ((error = git_config_set_bool(
1561
+ cfg, "core.precomposeunicode",
1562
+ git_path_does_fs_decompose_unicode(work_dir))) < 0)
1563
+ return error;
1564
+ /* on non-iconv platforms, don't even set core.precomposeunicode */
1565
+ #endif
1566
+
1567
+ return 0;
1568
+ }
1569
+
1570
+ static int repo_init_config(
1571
+ const char *repo_dir,
1572
+ const char *work_dir,
1573
+ uint32_t flags,
1574
+ uint32_t mode)
1575
+ {
1576
+ int error = 0;
1577
+ git_buf cfg_path = GIT_BUF_INIT, worktree_path = GIT_BUF_INIT;
1578
+ git_config *config = NULL;
1579
+ bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0);
1580
+ bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0);
1581
+
1582
+ if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0)
1583
+ goto cleanup;
1584
+
1585
+ if (is_reinit && (error = check_repositoryformatversion(config)) < 0)
953
1586
  goto cleanup;
954
1587
 
955
- SET_REPO_CONFIG(
956
- bool, "core.bare", (opts->flags & GIT_REPOSITORY_INIT_BARE) != 0);
957
- SET_REPO_CONFIG(
958
- int32, "core.repositoryformatversion", GIT_REPO_VERSION);
959
- SET_REPO_CONFIG(
960
- bool, "core.filemode", is_chmod_supported(git_buf_cstr(&cfg_path)));
1588
+ #define SET_REPO_CONFIG(TYPE, NAME, VAL) do { \
1589
+ if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \
1590
+ goto cleanup; } while (0)
1591
+
1592
+ SET_REPO_CONFIG(bool, "core.bare", is_bare);
1593
+ SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
961
1594
 
962
- if (!(opts->flags & GIT_REPOSITORY_INIT_BARE)) {
1595
+ if ((error = repo_init_fs_configs(
1596
+ config, cfg_path.ptr, repo_dir, work_dir, !is_reinit)) < 0)
1597
+ goto cleanup;
1598
+
1599
+ if (!is_bare) {
963
1600
  SET_REPO_CONFIG(bool, "core.logallrefupdates", true);
964
1601
 
965
- if (!are_symlinks_supported(work_dir))
966
- SET_REPO_CONFIG(bool, "core.symlinks", false);
1602
+ if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) {
1603
+ if ((error = git_buf_sets(&worktree_path, work_dir)) < 0)
1604
+ goto cleanup;
967
1605
 
968
- if (!(opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD)) {
969
- SET_REPO_CONFIG(string, "core.worktree", work_dir);
970
- }
971
- else if ((opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0) {
1606
+ if ((flags & GIT_REPOSITORY_INIT_RELATIVE_GITLINK))
1607
+ if ((error = git_path_make_relative(&worktree_path, repo_dir)) < 0)
1608
+ goto cleanup;
1609
+
1610
+ SET_REPO_CONFIG(string, "core.worktree", worktree_path.ptr);
1611
+ } else if (is_reinit) {
972
1612
  if (git_config_delete_entry(config, "core.worktree") < 0)
973
- giterr_clear();
1613
+ git_error_clear();
974
1614
  }
975
- } else {
976
- if (!are_symlinks_supported(repo_dir))
977
- SET_REPO_CONFIG(bool, "core.symlinks", false);
978
1615
  }
979
1616
 
980
- if (!(opts->flags & GIT_REPOSITORY_INIT__IS_REINIT) &&
981
- is_filesystem_case_insensitive(repo_dir))
982
- SET_REPO_CONFIG(bool, "core.ignorecase", true);
983
-
984
- if (opts->mode == GIT_REPOSITORY_INIT_SHARED_GROUP) {
1617
+ if (mode == GIT_REPOSITORY_INIT_SHARED_GROUP) {
985
1618
  SET_REPO_CONFIG(int32, "core.sharedrepository", 1);
986
1619
  SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
987
1620
  }
988
- else if (opts->mode == GIT_REPOSITORY_INIT_SHARED_ALL) {
1621
+ else if (mode == GIT_REPOSITORY_INIT_SHARED_ALL) {
989
1622
  SET_REPO_CONFIG(int32, "core.sharedrepository", 2);
990
1623
  SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
991
1624
  }
992
1625
 
993
1626
  cleanup:
994
- git_buf_free(&cfg_path);
1627
+ git_buf_dispose(&cfg_path);
1628
+ git_buf_dispose(&worktree_path);
1629
+ git_config_free(config);
1630
+
1631
+ return error;
1632
+ }
1633
+
1634
+ static int repo_reinit_submodule_fs(git_submodule *sm, const char *n, void *p)
1635
+ {
1636
+ git_repository *smrepo = NULL;
1637
+ GIT_UNUSED(n); GIT_UNUSED(p);
1638
+
1639
+ if (git_submodule_open(&smrepo, sm) < 0 ||
1640
+ git_repository_reinit_filesystem(smrepo, true) < 0)
1641
+ git_error_clear();
1642
+ git_repository_free(smrepo);
1643
+
1644
+ return 0;
1645
+ }
1646
+
1647
+ int git_repository_reinit_filesystem(git_repository *repo, int recurse)
1648
+ {
1649
+ int error = 0;
1650
+ git_buf path = GIT_BUF_INIT;
1651
+ git_config *config = NULL;
1652
+ const char *repo_dir = git_repository_path(repo);
1653
+
1654
+ if (!(error = repo_local_config(&config, &path, repo, repo_dir)))
1655
+ error = repo_init_fs_configs(
1656
+ config, path.ptr, repo_dir, git_repository_workdir(repo), true);
1657
+
995
1658
  git_config_free(config);
1659
+ git_buf_dispose(&path);
1660
+
1661
+ git_repository__cvar_cache_clear(repo);
1662
+
1663
+ if (!repo->is_bare && recurse)
1664
+ (void)git_submodule_foreach(repo, repo_reinit_submodule_fs, NULL);
996
1665
 
997
1666
  return error;
998
1667
  }
@@ -1028,27 +1697,28 @@ static int repo_write_template(
1028
1697
 
1029
1698
  #ifdef GIT_WIN32
1030
1699
  if (!error && hidden) {
1031
- if (p_hide_directory__w32(path.ptr) < 0)
1700
+ if (git_win32__set_hidden(path.ptr, true) < 0)
1032
1701
  error = -1;
1033
1702
  }
1034
1703
  #else
1035
1704
  GIT_UNUSED(hidden);
1036
1705
  #endif
1037
1706
 
1038
- git_buf_free(&path);
1707
+ git_buf_dispose(&path);
1039
1708
 
1040
1709
  if (error)
1041
- giterr_set(GITERR_OS,
1042
- "Failed to initialize repository with template '%s'", file);
1710
+ git_error_set(GIT_ERROR_OS,
1711
+ "failed to initialize repository with template '%s'", file);
1043
1712
 
1044
1713
  return error;
1045
1714
  }
1046
1715
 
1047
1716
  static int repo_write_gitlink(
1048
- const char *in_dir, const char *to_repo)
1717
+ const char *in_dir, const char *to_repo, bool use_relative_path)
1049
1718
  {
1050
1719
  int error;
1051
1720
  git_buf buf = GIT_BUF_INIT;
1721
+ git_buf path_to_repo = GIT_BUF_INIT;
1052
1722
  struct stat st;
1053
1723
 
1054
1724
  git_path_dirname_r(&buf, to_repo);
@@ -1068,21 +1738,28 @@ static int repo_write_gitlink(
1068
1738
  goto cleanup;
1069
1739
 
1070
1740
  if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) {
1071
- giterr_set(GITERR_REPOSITORY,
1072
- "Cannot overwrite gitlink file into path '%s'", in_dir);
1741
+ git_error_set(GIT_ERROR_REPOSITORY,
1742
+ "cannot overwrite gitlink file into path '%s'", in_dir);
1073
1743
  error = GIT_EEXISTS;
1074
1744
  goto cleanup;
1075
1745
  }
1076
1746
 
1077
1747
  git_buf_clear(&buf);
1078
1748
 
1079
- error = git_buf_printf(&buf, "%s %s", GIT_FILE_CONTENT_PREFIX, to_repo);
1749
+ error = git_buf_sets(&path_to_repo, to_repo);
1750
+
1751
+ if (!error && use_relative_path)
1752
+ error = git_path_make_relative(&path_to_repo, in_dir);
1753
+
1754
+ if (!error)
1755
+ error = git_buf_join(&buf, ' ', GIT_FILE_CONTENT_PREFIX, path_to_repo.ptr);
1080
1756
 
1081
1757
  if (!error)
1082
1758
  error = repo_write_template(in_dir, true, DOT_GIT, 0666, true, buf.ptr);
1083
1759
 
1084
1760
  cleanup:
1085
- git_buf_free(&buf);
1761
+ git_buf_dispose(&buf);
1762
+ git_buf_dispose(&path_to_repo);
1086
1763
  return error;
1087
1764
  }
1088
1765
 
@@ -1109,13 +1786,14 @@ static int repo_init_structure(
1109
1786
  bool external_tpl =
1110
1787
  ((opts->flags & GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE) != 0);
1111
1788
  mode_t dmode = pick_dir_mode(opts);
1789
+ bool chmod = opts->mode != GIT_REPOSITORY_INIT_SHARED_UMASK;
1112
1790
 
1113
1791
  /* Hide the ".git" directory */
1114
1792
  #ifdef GIT_WIN32
1115
1793
  if ((opts->flags & GIT_REPOSITORY_INIT__HAS_DOTGIT) != 0) {
1116
- if (p_hide_directory__w32(repo_dir) < 0) {
1117
- giterr_set(GITERR_REPOSITORY,
1118
- "Failed to mark Git repository folder as hidden");
1794
+ if (git_win32__set_hidden(repo_dir, true) < 0) {
1795
+ git_error_set(GIT_ERROR_OS,
1796
+ "failed to mark Git repository folder as hidden");
1119
1797
  return -1;
1120
1798
  }
1121
1799
  }
@@ -1125,41 +1803,55 @@ static int repo_init_structure(
1125
1803
  if ((opts->flags & GIT_REPOSITORY_INIT_BARE) == 0 &&
1126
1804
  (opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD) == 0)
1127
1805
  {
1128
- if (repo_write_gitlink(work_dir, repo_dir) < 0)
1806
+ if (repo_write_gitlink(work_dir, repo_dir, opts->flags & GIT_REPOSITORY_INIT_RELATIVE_GITLINK) < 0)
1129
1807
  return -1;
1130
1808
  }
1131
1809
 
1132
1810
  /* Copy external template if requested */
1133
1811
  if (external_tpl) {
1134
- git_config *cfg;
1135
- const char *tdir;
1812
+ git_config *cfg = NULL;
1813
+ const char *tdir = NULL;
1814
+ bool default_template = false;
1815
+ git_buf template_buf = GIT_BUF_INIT;
1136
1816
 
1137
1817
  if (opts->template_path)
1138
1818
  tdir = opts->template_path;
1139
- else if ((error = git_config_open_default(&cfg)) < 0)
1140
- return error;
1141
- else {
1142
- error = git_config_get_string(&tdir, cfg, "init.templatedir");
1143
-
1144
- git_config_free(cfg);
1819
+ else if ((error = git_config_open_default(&cfg)) >= 0) {
1820
+ if (!git_config_get_path(&template_buf, cfg, "init.templatedir"))
1821
+ tdir = template_buf.ptr;
1822
+ git_error_clear();
1823
+ }
1145
1824
 
1146
- if (error && error != GIT_ENOTFOUND)
1147
- return error;
1825
+ if (!tdir) {
1826
+ if (!(error = git_sysdir_find_template_dir(&template_buf)))
1827
+ tdir = template_buf.ptr;
1828
+ default_template = true;
1829
+ }
1148
1830
 
1149
- giterr_clear();
1150
- tdir = GIT_TEMPLATE_DIR;
1831
+ /*
1832
+ * If tdir was the empty string, treat it like tdir was a path to an
1833
+ * empty directory (so, don't do any copying). This is the behavior
1834
+ * that git(1) exhibits, although it doesn't seem to be officially
1835
+ * documented.
1836
+ */
1837
+ if (tdir && git__strcmp(tdir, "") != 0) {
1838
+ uint32_t cpflags = GIT_CPDIR_COPY_SYMLINKS |
1839
+ GIT_CPDIR_SIMPLE_TO_MODE |
1840
+ GIT_CPDIR_COPY_DOTFILES;
1841
+ if (opts->mode != GIT_REPOSITORY_INIT_SHARED_UMASK)
1842
+ cpflags |= GIT_CPDIR_CHMOD_DIRS;
1843
+ error = git_futils_cp_r(tdir, repo_dir, cpflags, dmode);
1151
1844
  }
1152
1845
 
1153
- error = git_futils_cp_r(tdir, repo_dir,
1154
- GIT_CPDIR_COPY_SYMLINKS | GIT_CPDIR_CHMOD_DIRS |
1155
- GIT_CPDIR_SIMPLE_TO_MODE, dmode);
1846
+ git_buf_dispose(&template_buf);
1847
+ git_config_free(cfg);
1156
1848
 
1157
1849
  if (error < 0) {
1158
- if (strcmp(tdir, GIT_TEMPLATE_DIR) != 0)
1850
+ if (!default_template)
1159
1851
  return error;
1160
1852
 
1161
1853
  /* if template was default, ignore error and use internal */
1162
- giterr_clear();
1854
+ git_error_clear();
1163
1855
  external_tpl = false;
1164
1856
  error = 0;
1165
1857
  }
@@ -1170,9 +1862,14 @@ static int repo_init_structure(
1170
1862
  * - only create files if no external template was specified
1171
1863
  */
1172
1864
  for (tpl = repo_template; !error && tpl->path; ++tpl) {
1173
- if (!tpl->content)
1174
- error = git_futils_mkdir(
1175
- tpl->path, repo_dir, dmode, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD);
1865
+ if (!tpl->content) {
1866
+ uint32_t mkdir_flags = GIT_MKDIR_PATH;
1867
+ if (chmod)
1868
+ mkdir_flags |= GIT_MKDIR_CHMOD;
1869
+
1870
+ error = git_futils_mkdir_relative(
1871
+ tpl->path, repo_dir, dmode, mkdir_flags, NULL);
1872
+ }
1176
1873
  else if (!external_tpl) {
1177
1874
  const char *content = tpl->content;
1178
1875
 
@@ -1193,7 +1890,7 @@ static int mkdir_parent(git_buf *buf, uint32_t mode, bool skip2)
1193
1890
  * don't try to set gid or grant world write access
1194
1891
  */
1195
1892
  return git_futils_mkdir(
1196
- buf->ptr, NULL, mode & ~(S_ISGID | 0002),
1893
+ buf->ptr, mode & ~(S_ISGID | 0002),
1197
1894
  GIT_MKDIR_PATH | GIT_MKDIR_VERIFY_DIR |
1198
1895
  (skip2 ? GIT_MKDIR_SKIP_LAST2 : GIT_MKDIR_SKIP_LAST));
1199
1896
  }
@@ -1256,7 +1953,7 @@ static int repo_init_directories(
1256
1953
  if (git_path_dirname_r(wd_path, repo_path->ptr) < 0)
1257
1954
  return -1;
1258
1955
  } else {
1259
- giterr_set(GITERR_REPOSITORY, "Cannot pick working directory"
1956
+ git_error_set(GIT_ERROR_REPOSITORY, "cannot pick working directory"
1260
1957
  " for non-bare repository that isn't a '.git' directory");
1261
1958
  return -1;
1262
1959
  }
@@ -1297,14 +1994,14 @@ static int repo_init_directories(
1297
1994
  /* create path #4 */
1298
1995
  if (wd_path->size > 0 &&
1299
1996
  (error = git_futils_mkdir(
1300
- wd_path->ptr, NULL, dirmode & ~S_ISGID,
1997
+ wd_path->ptr, dirmode & ~S_ISGID,
1301
1998
  GIT_MKDIR_VERIFY_DIR)) < 0)
1302
1999
  return error;
1303
2000
 
1304
2001
  /* create path #2 (if not the same as #4) */
1305
2002
  if (!natural_wd &&
1306
2003
  (error = git_futils_mkdir(
1307
- repo_path->ptr, NULL, dirmode & ~S_ISGID,
2004
+ repo_path->ptr, dirmode & ~S_ISGID,
1308
2005
  GIT_MKDIR_VERIFY_DIR | GIT_MKDIR_SKIP_LAST)) < 0)
1309
2006
  return error;
1310
2007
  }
@@ -1314,7 +2011,7 @@ static int repo_init_directories(
1314
2011
  has_dotgit)
1315
2012
  {
1316
2013
  /* create path #1 */
1317
- error = git_futils_mkdir(repo_path->ptr, NULL, dirmode,
2014
+ error = git_futils_mkdir(repo_path->ptr, dirmode,
1318
2015
  GIT_MKDIR_VERIFY_DIR | ((dirmode & S_ISGID) ? GIT_MKDIR_CHMOD : 0));
1319
2016
  }
1320
2017
 
@@ -1360,21 +2057,24 @@ int git_repository_init_ext(
1360
2057
  git_repository_init_options *opts)
1361
2058
  {
1362
2059
  int error;
1363
- git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT;
2060
+ git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT,
2061
+ common_path = GIT_BUF_INIT;
2062
+ const char *wd;
1364
2063
 
1365
2064
  assert(out && given_repo && opts);
1366
2065
 
1367
- GITERR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
2066
+ GIT_ERROR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
1368
2067
 
1369
2068
  error = repo_init_directories(&repo_path, &wd_path, given_repo, opts);
1370
2069
  if (error < 0)
1371
2070
  goto cleanup;
1372
2071
 
1373
- if (valid_repository_path(&repo_path)) {
2072
+ wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path);
2073
+ if (valid_repository_path(&repo_path, &common_path)) {
1374
2074
 
1375
2075
  if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) {
1376
- giterr_set(GITERR_REPOSITORY,
1377
- "Attempt to reinitialize '%s'", given_repo);
2076
+ git_error_set(GIT_ERROR_REPOSITORY,
2077
+ "attempt to reinitialize '%s'", given_repo);
1378
2078
  error = GIT_EEXISTS;
1379
2079
  goto cleanup;
1380
2080
  }
@@ -1382,29 +2082,30 @@ int git_repository_init_ext(
1382
2082
  opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT;
1383
2083
 
1384
2084
  error = repo_init_config(
1385
- git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts);
2085
+ repo_path.ptr, wd, opts->flags, opts->mode);
1386
2086
 
1387
2087
  /* TODO: reinitialize the templates */
1388
2088
  }
1389
2089
  else {
1390
2090
  if (!(error = repo_init_structure(
1391
- git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts)) &&
2091
+ repo_path.ptr, wd, opts)) &&
1392
2092
  !(error = repo_init_config(
1393
- git_buf_cstr(&repo_path), git_buf_cstr(&wd_path), opts)))
1394
- error = repo_init_create_head(
1395
- git_buf_cstr(&repo_path), opts->initial_head);
2093
+ repo_path.ptr, wd, opts->flags, opts->mode)))
2094
+ error = git_repository_create_head(
2095
+ repo_path.ptr, opts->initial_head);
1396
2096
  }
1397
2097
  if (error < 0)
1398
2098
  goto cleanup;
1399
2099
 
1400
- error = git_repository_open(out, git_buf_cstr(&repo_path));
2100
+ error = git_repository_open(out, repo_path.ptr);
1401
2101
 
1402
2102
  if (!error && opts->origin_url)
1403
2103
  error = repo_init_create_origin(*out, opts->origin_url);
1404
2104
 
1405
2105
  cleanup:
1406
- git_buf_free(&repo_path);
1407
- git_buf_free(&wd_path);
2106
+ git_buf_dispose(&common_path);
2107
+ git_buf_dispose(&repo_path);
2108
+ git_buf_dispose(&wd_path);
1408
2109
 
1409
2110
  return error;
1410
2111
  }
@@ -1421,7 +2122,7 @@ int git_repository_head_detached(git_repository *repo)
1421
2122
  if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0)
1422
2123
  return -1;
1423
2124
 
1424
- if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
2125
+ if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC) {
1425
2126
  git_reference_free(ref);
1426
2127
  return 0;
1427
2128
  }
@@ -1432,15 +2133,40 @@ int git_repository_head_detached(git_repository *repo)
1432
2133
  return exists;
1433
2134
  }
1434
2135
 
2136
+ static int get_worktree_file_path(git_buf *out, git_repository *repo, const char *worktree, const char *file)
2137
+ {
2138
+ git_buf_clear(out);
2139
+ return git_buf_printf(out, "%s/worktrees/%s/%s", repo->commondir, worktree, file);
2140
+ }
2141
+
2142
+ int git_repository_head_detached_for_worktree(git_repository *repo, const char *name)
2143
+ {
2144
+ git_reference *ref = NULL;
2145
+ int error;
2146
+
2147
+ assert(repo && name);
2148
+
2149
+ if ((error = git_repository_head_for_worktree(&ref, repo, name)) < 0)
2150
+ goto out;
2151
+
2152
+ error = (git_reference_type(ref) != GIT_REFERENCE_SYMBOLIC);
2153
+ out:
2154
+ git_reference_free(ref);
2155
+
2156
+ return error;
2157
+ }
2158
+
1435
2159
  int git_repository_head(git_reference **head_out, git_repository *repo)
1436
2160
  {
1437
2161
  git_reference *head;
1438
2162
  int error;
1439
2163
 
2164
+ assert(head_out);
2165
+
1440
2166
  if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0)
1441
2167
  return error;
1442
2168
 
1443
- if (git_reference_type(head) == GIT_REF_OID) {
2169
+ if (git_reference_type(head) == GIT_REFERENCE_DIRECT) {
1444
2170
  *head_out = head;
1445
2171
  return 0;
1446
2172
  }
@@ -1448,10 +2174,75 @@ int git_repository_head(git_reference **head_out, git_repository *repo)
1448
2174
  error = git_reference_lookup_resolved(head_out, repo, git_reference_symbolic_target(head), -1);
1449
2175
  git_reference_free(head);
1450
2176
 
1451
- return error == GIT_ENOTFOUND ? GIT_EORPHANEDHEAD : error;
2177
+ return error == GIT_ENOTFOUND ? GIT_EUNBORNBRANCH : error;
2178
+ }
2179
+
2180
+ int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name)
2181
+ {
2182
+ git_buf path = GIT_BUF_INIT;
2183
+ git_reference *head = NULL;
2184
+ int error;
2185
+
2186
+ assert(out && repo && name);
2187
+
2188
+ *out = NULL;
2189
+
2190
+ if ((error = get_worktree_file_path(&path, repo, name, GIT_HEAD_FILE)) < 0 ||
2191
+ (error = git_reference__read_head(&head, repo, path.ptr)) < 0)
2192
+ goto out;
2193
+
2194
+ if (git_reference_type(head) != GIT_REFERENCE_DIRECT) {
2195
+ git_reference *resolved;
2196
+
2197
+ error = git_reference_lookup_resolved(&resolved, repo, git_reference_symbolic_target(head), -1);
2198
+ git_reference_free(head);
2199
+ head = resolved;
2200
+ }
2201
+
2202
+ *out = head;
2203
+
2204
+ out:
2205
+ if (error)
2206
+ git_reference_free(head);
2207
+
2208
+ git_buf_dispose(&path);
2209
+
2210
+ return error;
1452
2211
  }
1453
2212
 
1454
- int git_repository_head_orphan(git_repository *repo)
2213
+ int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload)
2214
+ {
2215
+ git_strarray worktrees = GIT_VECTOR_INIT;
2216
+ git_buf path = GIT_BUF_INIT;
2217
+ int error;
2218
+ size_t i;
2219
+
2220
+ /* Execute callback for HEAD of commondir */
2221
+ if ((error = git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE)) < 0 ||
2222
+ (error = cb(repo, path.ptr, payload) != 0))
2223
+ goto out;
2224
+
2225
+ if ((error = git_worktree_list(&worktrees, repo)) < 0) {
2226
+ error = 0;
2227
+ goto out;
2228
+ }
2229
+
2230
+ /* Execute callback for all worktree HEADs */
2231
+ for (i = 0; i < worktrees.count; i++) {
2232
+ if (get_worktree_file_path(&path, repo, worktrees.strings[i], GIT_HEAD_FILE) < 0)
2233
+ continue;
2234
+
2235
+ if ((error = cb(repo, path.ptr, payload)) != 0)
2236
+ goto out;
2237
+ }
2238
+
2239
+ out:
2240
+ git_buf_dispose(&path);
2241
+ git_strarray_free(&worktrees);
2242
+ return error;
2243
+ }
2244
+
2245
+ int git_repository_head_unborn(git_repository *repo)
1455
2246
  {
1456
2247
  git_reference *ref = NULL;
1457
2248
  int error;
@@ -1459,8 +2250,10 @@ int git_repository_head_orphan(git_repository *repo)
1459
2250
  error = git_repository_head(&ref, repo);
1460
2251
  git_reference_free(ref);
1461
2252
 
1462
- if (error == GIT_EORPHANEDHEAD)
2253
+ if (error == GIT_EUNBORNBRANCH) {
2254
+ git_error_clear();
1463
2255
  return 1;
2256
+ }
1464
2257
 
1465
2258
  if (error < 0)
1466
2259
  return -1;
@@ -1472,15 +2265,14 @@ static int at_least_one_cb(const char *refname, void *payload)
1472
2265
  {
1473
2266
  GIT_UNUSED(refname);
1474
2267
  GIT_UNUSED(payload);
1475
-
1476
- return GIT_EUSER;
2268
+ return GIT_PASSTHROUGH;
1477
2269
  }
1478
2270
 
1479
2271
  static int repo_contains_no_reference(git_repository *repo)
1480
2272
  {
1481
2273
  int error = git_reference_foreach_name(repo, &at_least_one_cb, NULL);
1482
2274
 
1483
- if (error == GIT_EUSER)
2275
+ if (error == GIT_PASSTHROUGH)
1484
2276
  return 0;
1485
2277
 
1486
2278
  if (!error)
@@ -1492,33 +2284,69 @@ static int repo_contains_no_reference(git_repository *repo)
1492
2284
  int git_repository_is_empty(git_repository *repo)
1493
2285
  {
1494
2286
  git_reference *head = NULL;
1495
- int error;
2287
+ int is_empty = 0;
1496
2288
 
1497
2289
  if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0)
1498
2290
  return -1;
1499
2291
 
1500
- if (!(error = git_reference_type(head) == GIT_REF_SYMBOLIC))
1501
- goto cleanup;
2292
+ if (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC)
2293
+ is_empty =
2294
+ (strcmp(git_reference_symbolic_target(head),
2295
+ GIT_REFS_HEADS_DIR "master") == 0) &&
2296
+ repo_contains_no_reference(repo);
1502
2297
 
1503
- if (!(error = strcmp(
1504
- git_reference_symbolic_target(head),
1505
- GIT_REFS_HEADS_DIR "master") == 0))
1506
- goto cleanup;
2298
+ git_reference_free(head);
1507
2299
 
1508
- error = repo_contains_no_reference(repo);
2300
+ return is_empty;
2301
+ }
1509
2302
 
1510
- cleanup:
1511
- git_reference_free(head);
1512
- return error < 0 ? -1 : error;
2303
+ int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
2304
+ {
2305
+ const char *parent;
2306
+
2307
+ switch (items[item].parent) {
2308
+ case GIT_REPOSITORY_ITEM_GITDIR:
2309
+ parent = git_repository_path(repo);
2310
+ break;
2311
+ case GIT_REPOSITORY_ITEM_WORKDIR:
2312
+ parent = git_repository_workdir(repo);
2313
+ break;
2314
+ case GIT_REPOSITORY_ITEM_COMMONDIR:
2315
+ parent = git_repository_commondir(repo);
2316
+ break;
2317
+ default:
2318
+ git_error_set(GIT_ERROR_INVALID, "invalid item directory");
2319
+ return -1;
2320
+ }
2321
+
2322
+ if (parent == NULL) {
2323
+ git_error_set(GIT_ERROR_INVALID, "path cannot exist in repository");
2324
+ return GIT_ENOTFOUND;
2325
+ }
2326
+
2327
+ if (git_buf_sets(out, parent) < 0)
2328
+ return -1;
2329
+
2330
+ if (items[item].name) {
2331
+ if (git_buf_joinpath(out, parent, items[item].name) < 0)
2332
+ return -1;
2333
+ }
2334
+
2335
+ if (items[item].directory) {
2336
+ if (git_path_to_dir(out) < 0)
2337
+ return -1;
2338
+ }
2339
+
2340
+ return 0;
1513
2341
  }
1514
2342
 
1515
- const char *git_repository_path(git_repository *repo)
2343
+ const char *git_repository_path(const git_repository *repo)
1516
2344
  {
1517
2345
  assert(repo);
1518
- return repo->path_repository;
2346
+ return repo->gitdir;
1519
2347
  }
1520
2348
 
1521
- const char *git_repository_workdir(git_repository *repo)
2349
+ const char *git_repository_workdir(const git_repository *repo)
1522
2350
  {
1523
2351
  assert(repo);
1524
2352
 
@@ -1528,6 +2356,12 @@ const char *git_repository_workdir(git_repository *repo)
1528
2356
  return repo->workdir;
1529
2357
  }
1530
2358
 
2359
+ const char *git_repository_commondir(const git_repository *repo)
2360
+ {
2361
+ assert(repo);
2362
+ return repo->commondir;
2363
+ }
2364
+
1531
2365
  int git_repository_set_workdir(
1532
2366
  git_repository *repo, const char *workdir, int update_gitlink)
1533
2367
  {
@@ -1548,7 +2382,7 @@ int git_repository_set_workdir(
1548
2382
  if (git_repository_config__weakptr(&config, repo) < 0)
1549
2383
  return -1;
1550
2384
 
1551
- error = repo_write_gitlink(path.ptr, git_repository_path(repo));
2385
+ error = repo_write_gitlink(path.ptr, git_repository_path(repo), false);
1552
2386
 
1553
2387
  /* passthrough error means gitlink is unnecessary */
1554
2388
  if (error == GIT_PASSTHROUGH)
@@ -1572,12 +2406,44 @@ int git_repository_set_workdir(
1572
2406
  return error;
1573
2407
  }
1574
2408
 
1575
- int git_repository_is_bare(git_repository *repo)
2409
+ int git_repository_is_bare(const git_repository *repo)
1576
2410
  {
1577
2411
  assert(repo);
1578
2412
  return repo->is_bare;
1579
2413
  }
1580
2414
 
2415
+ int git_repository_is_worktree(const git_repository *repo)
2416
+ {
2417
+ assert(repo);
2418
+ return repo->is_worktree;
2419
+ }
2420
+
2421
+ int git_repository_set_bare(git_repository *repo)
2422
+ {
2423
+ int error;
2424
+ git_config *config;
2425
+
2426
+ assert(repo);
2427
+
2428
+ if (repo->is_bare)
2429
+ return 0;
2430
+
2431
+ if ((error = git_repository_config__weakptr(&config, repo)) < 0)
2432
+ return error;
2433
+
2434
+ if ((error = git_config_set_bool(config, "core.bare", true)) < 0)
2435
+ return error;
2436
+
2437
+ if ((error = git_config__update_entry(config, "core.worktree", NULL, true, true)) < 0)
2438
+ return error;
2439
+
2440
+ git__free(repo->workdir);
2441
+ repo->workdir = NULL;
2442
+ repo->is_bare = 1;
2443
+
2444
+ return 0;
2445
+ }
2446
+
1581
2447
  int git_repository_head_tree(git_tree **tree, git_repository *repo)
1582
2448
  {
1583
2449
  git_reference *head;
@@ -1587,7 +2453,7 @@ int git_repository_head_tree(git_tree **tree, git_repository *repo)
1587
2453
  if ((error = git_repository_head(&head, repo)) < 0)
1588
2454
  return error;
1589
2455
 
1590
- if ((error = git_reference_peel(&obj, head, GIT_OBJ_TREE)) < 0)
2456
+ if ((error = git_reference_peel(&obj, head, GIT_OBJECT_TREE)) < 0)
1591
2457
  goto cleanup;
1592
2458
 
1593
2459
  *tree = (git_tree *)obj;
@@ -1597,33 +2463,48 @@ cleanup:
1597
2463
  return error;
1598
2464
  }
1599
2465
 
1600
- int git_repository_message(char *buffer, size_t len, git_repository *repo)
2466
+ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head)
1601
2467
  {
1602
- git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
2468
+ git_filebuf file = GIT_FILEBUF_INIT;
2469
+ git_buf file_path = GIT_BUF_INIT;
2470
+ char orig_head_str[GIT_OID_HEXSZ];
2471
+ int error = 0;
2472
+
2473
+ git_oid_fmt(orig_head_str, orig_head);
2474
+
2475
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 &&
2476
+ (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) == 0 &&
2477
+ (error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_HEXSZ, orig_head_str)) == 0)
2478
+ error = git_filebuf_commit(&file);
2479
+
2480
+ if (error < 0)
2481
+ git_filebuf_cleanup(&file);
2482
+
2483
+ git_buf_dispose(&file_path);
2484
+
2485
+ return error;
2486
+ }
2487
+
2488
+ int git_repository_message(git_buf *out, git_repository *repo)
2489
+ {
2490
+ git_buf path = GIT_BUF_INIT;
1603
2491
  struct stat st;
1604
2492
  int error;
1605
2493
 
1606
- if (buffer != NULL)
1607
- *buffer = '\0';
2494
+ git_buf_sanitize(out);
1608
2495
 
1609
- if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
2496
+ if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
1610
2497
  return -1;
1611
2498
 
1612
2499
  if ((error = p_stat(git_buf_cstr(&path), &st)) < 0) {
1613
2500
  if (errno == ENOENT)
1614
2501
  error = GIT_ENOTFOUND;
1615
- giterr_set(GITERR_OS, "Could not access message file");
1616
- }
1617
- else if (buffer != NULL) {
1618
- error = git_futils_readbuffer(&buf, git_buf_cstr(&path));
1619
- git_buf_copy_cstr(buffer, len, &buf);
2502
+ git_error_set(GIT_ERROR_OS, "could not access message file");
2503
+ } else {
2504
+ error = git_futils_readbuffer(out, git_buf_cstr(&path));
1620
2505
  }
1621
2506
 
1622
- git_buf_free(&path);
1623
- git_buf_free(&buf);
1624
-
1625
- if (!error)
1626
- error = (int)st.st_size + 1; /* add 1 for NUL byte */
2507
+ git_buf_dispose(&path);
1627
2508
 
1628
2509
  return error;
1629
2510
  }
@@ -1633,11 +2514,11 @@ int git_repository_message_remove(git_repository *repo)
1633
2514
  git_buf path = GIT_BUF_INIT;
1634
2515
  int error;
1635
2516
 
1636
- if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
2517
+ if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0)
1637
2518
  return -1;
1638
2519
 
1639
2520
  error = p_unlink(git_buf_cstr(&path));
1640
- git_buf_free(&path);
2521
+ git_buf_dispose(&path);
1641
2522
 
1642
2523
  return error;
1643
2524
  }
@@ -1646,11 +2527,11 @@ int git_repository_hashfile(
1646
2527
  git_oid *out,
1647
2528
  git_repository *repo,
1648
2529
  const char *path,
1649
- git_otype type,
2530
+ git_object_t type,
1650
2531
  const char *as_path)
1651
2532
  {
1652
2533
  int error;
1653
- git_vector filters = GIT_VECTOR_INIT;
2534
+ git_filter_list *fl = NULL;
1654
2535
  git_file fd = -1;
1655
2536
  git_off_t len;
1656
2537
  git_buf full_path = GIT_BUF_INIT;
@@ -1663,7 +2544,7 @@ int git_repository_hashfile(
1663
2544
  */
1664
2545
 
1665
2546
  error = git_path_join_unrooted(
1666
- &full_path, path, repo ? git_repository_workdir(repo) : NULL, NULL);
2547
+ &full_path, path, git_repository_workdir(repo), NULL);
1667
2548
  if (error < 0)
1668
2549
  return error;
1669
2550
 
@@ -1672,7 +2553,9 @@ int git_repository_hashfile(
1672
2553
 
1673
2554
  /* passing empty string for "as_path" indicated --no-filters */
1674
2555
  if (strlen(as_path) > 0) {
1675
- error = git_filters_load(&filters, repo, as_path, GIT_FILTER_TO_ODB);
2556
+ error = git_filter_list_load(
2557
+ &fl, repo, NULL, as_path,
2558
+ GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT);
1676
2559
  if (error < 0)
1677
2560
  return error;
1678
2561
  } else {
@@ -1694,49 +2577,125 @@ int git_repository_hashfile(
1694
2577
  }
1695
2578
 
1696
2579
  if (!git__is_sizet(len)) {
1697
- giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
2580
+ git_error_set(GIT_ERROR_OS, "file size overflow for 32-bit systems");
1698
2581
  error = -1;
1699
2582
  goto cleanup;
1700
2583
  }
1701
2584
 
1702
- error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, &filters);
2585
+ error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, fl);
1703
2586
 
1704
2587
  cleanup:
1705
2588
  if (fd >= 0)
1706
2589
  p_close(fd);
1707
- git_filters_free(&filters);
1708
- git_buf_free(&full_path);
2590
+ git_filter_list_free(fl);
2591
+ git_buf_dispose(&full_path);
1709
2592
 
1710
2593
  return error;
1711
2594
  }
1712
2595
 
1713
- static bool looks_like_a_branch(const char *refname)
2596
+ static int checkout_message(git_buf *out, git_reference *old, const char *new)
2597
+ {
2598
+ git_buf_puts(out, "checkout: moving from ");
2599
+
2600
+ if (git_reference_type(old) == GIT_REFERENCE_SYMBOLIC)
2601
+ git_buf_puts(out, git_reference__shorthand(git_reference_symbolic_target(old)));
2602
+ else
2603
+ git_buf_puts(out, git_oid_tostr_s(git_reference_target(old)));
2604
+
2605
+ git_buf_puts(out, " to ");
2606
+
2607
+ if (git_reference__is_branch(new) ||
2608
+ git_reference__is_tag(new) ||
2609
+ git_reference__is_remote(new))
2610
+ git_buf_puts(out, git_reference__shorthand(new));
2611
+ else
2612
+ git_buf_puts(out, new);
2613
+
2614
+ if (git_buf_oom(out))
2615
+ return -1;
2616
+
2617
+ return 0;
2618
+ }
2619
+
2620
+ static int detach(git_repository *repo, const git_oid *id, const char *new)
1714
2621
  {
1715
- return git__prefixcmp(refname, GIT_REFS_HEADS_DIR) == 0;
2622
+ int error;
2623
+ git_buf log_message = GIT_BUF_INIT;
2624
+ git_object *object = NULL, *peeled = NULL;
2625
+ git_reference *new_head = NULL, *current = NULL;
2626
+
2627
+ assert(repo && id);
2628
+
2629
+ if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
2630
+ return error;
2631
+
2632
+ if ((error = git_object_lookup(&object, repo, id, GIT_OBJECT_ANY)) < 0)
2633
+ goto cleanup;
2634
+
2635
+ if ((error = git_object_peel(&peeled, object, GIT_OBJECT_COMMIT)) < 0)
2636
+ goto cleanup;
2637
+
2638
+ if (new == NULL)
2639
+ new = git_oid_tostr_s(git_object_id(peeled));
2640
+
2641
+ if ((error = checkout_message(&log_message, current, new)) < 0)
2642
+ goto cleanup;
2643
+
2644
+ error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
2645
+
2646
+ cleanup:
2647
+ git_buf_dispose(&log_message);
2648
+ git_object_free(object);
2649
+ git_object_free(peeled);
2650
+ git_reference_free(current);
2651
+ git_reference_free(new_head);
2652
+ return error;
1716
2653
  }
1717
2654
 
1718
2655
  int git_repository_set_head(
1719
2656
  git_repository* repo,
1720
2657
  const char* refname)
1721
2658
  {
1722
- git_reference *ref,
1723
- *new_head = NULL;
2659
+ git_reference *ref = NULL, *current = NULL, *new_head = NULL;
2660
+ git_buf log_message = GIT_BUF_INIT;
1724
2661
  int error;
1725
2662
 
1726
2663
  assert(repo && refname);
1727
2664
 
2665
+ if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
2666
+ return error;
2667
+
2668
+ if ((error = checkout_message(&log_message, current, refname)) < 0)
2669
+ goto cleanup;
2670
+
1728
2671
  error = git_reference_lookup(&ref, repo, refname);
1729
2672
  if (error < 0 && error != GIT_ENOTFOUND)
1730
- return error;
2673
+ goto cleanup;
2674
+
2675
+ if (ref && current->type == GIT_REFERENCE_SYMBOLIC && git__strcmp(current->target.symbolic, ref->name) &&
2676
+ git_reference_is_branch(ref) && git_branch_is_checked_out(ref)) {
2677
+ git_error_set(GIT_ERROR_REPOSITORY, "cannot set HEAD to reference '%s' as it is the current HEAD "
2678
+ "of a linked repository.", git_reference_name(ref));
2679
+ error = -1;
2680
+ goto cleanup;
2681
+ }
1731
2682
 
1732
2683
  if (!error) {
1733
- if (git_reference_is_branch(ref))
1734
- error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, git_reference_name(ref), 1);
1735
- else
1736
- error = git_repository_set_head_detached(repo, git_reference_target(ref));
1737
- } else if (looks_like_a_branch(refname))
1738
- error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname, 1);
2684
+ if (git_reference_is_branch(ref)) {
2685
+ error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
2686
+ git_reference_name(ref), true, git_buf_cstr(&log_message));
2687
+ } else {
2688
+ error = detach(repo, git_reference_target(ref),
2689
+ git_reference_is_tag(ref) || git_reference_is_remote(ref) ? refname : NULL);
2690
+ }
2691
+ } else if (git_reference__is_branch(refname)) {
2692
+ error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
2693
+ true, git_buf_cstr(&log_message));
2694
+ }
1739
2695
 
2696
+ cleanup:
2697
+ git_buf_dispose(&log_message);
2698
+ git_reference_free(current);
1740
2699
  git_reference_free(ref);
1741
2700
  git_reference_free(new_head);
1742
2701
  return error;
@@ -1746,50 +2705,48 @@ int git_repository_set_head_detached(
1746
2705
  git_repository* repo,
1747
2706
  const git_oid* commitish)
1748
2707
  {
1749
- int error;
1750
- git_object *object,
1751
- *peeled = NULL;
1752
- git_reference *new_head = NULL;
2708
+ return detach(repo, commitish, NULL);
2709
+ }
1753
2710
 
2711
+ int git_repository_set_head_detached_from_annotated(
2712
+ git_repository *repo,
2713
+ const git_annotated_commit *commitish)
2714
+ {
1754
2715
  assert(repo && commitish);
1755
2716
 
1756
- if ((error = git_object_lookup(&object, repo, commitish, GIT_OBJ_ANY)) < 0)
1757
- return error;
1758
-
1759
- if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
1760
- goto cleanup;
1761
-
1762
- error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), 1);
1763
-
1764
- cleanup:
1765
- git_object_free(object);
1766
- git_object_free(peeled);
1767
- git_reference_free(new_head);
1768
- return error;
2717
+ return detach(repo, git_annotated_commit_id(commitish), commitish->description);
1769
2718
  }
1770
2719
 
1771
- int git_repository_detach_head(
1772
- git_repository* repo)
2720
+ int git_repository_detach_head(git_repository* repo)
1773
2721
  {
1774
- git_reference *old_head = NULL,
1775
- *new_head = NULL;
2722
+ git_reference *old_head = NULL, *new_head = NULL, *current = NULL;
1776
2723
  git_object *object = NULL;
2724
+ git_buf log_message = GIT_BUF_INIT;
1777
2725
  int error;
1778
2726
 
1779
2727
  assert(repo);
1780
2728
 
1781
- if ((error = git_repository_head(&old_head, repo)) < 0)
2729
+ if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
1782
2730
  return error;
1783
2731
 
1784
- if ((error = git_object_lookup(&object, repo, git_reference_target(old_head), GIT_OBJ_COMMIT)) < 0)
2732
+ if ((error = git_repository_head(&old_head, repo)) < 0)
1785
2733
  goto cleanup;
1786
2734
 
1787
- error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_reference_target(old_head), 1);
2735
+ if ((error = git_object_lookup(&object, repo, git_reference_target(old_head), GIT_OBJECT_COMMIT)) < 0)
2736
+ goto cleanup;
2737
+
2738
+ if ((error = checkout_message(&log_message, current, git_oid_tostr_s(git_object_id(object)))) < 0)
2739
+ goto cleanup;
2740
+
2741
+ error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_reference_target(old_head),
2742
+ 1, git_buf_cstr(&log_message));
1788
2743
 
1789
2744
  cleanup:
2745
+ git_buf_dispose(&log_message);
1790
2746
  git_object_free(object);
1791
2747
  git_reference_free(old_head);
1792
2748
  git_reference_free(new_head);
2749
+ git_reference_free(current);
1793
2750
  return error;
1794
2751
  }
1795
2752
 
@@ -1804,7 +2761,7 @@ int git_repository_state(git_repository *repo)
1804
2761
 
1805
2762
  assert(repo);
1806
2763
 
1807
- if (git_buf_puts(&repo_path, repo->path_repository) < 0)
2764
+ if (git_buf_puts(&repo_path, repo->gitdir) < 0)
1808
2765
  return -1;
1809
2766
 
1810
2767
  if (git_path_contains_file(&repo_path, GIT_REBASE_MERGE_INTERACTIVE_FILE))
@@ -1819,30 +2776,157 @@ int git_repository_state(git_repository *repo)
1819
2776
  state = GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE;
1820
2777
  else if (git_path_contains_file(&repo_path, GIT_MERGE_HEAD_FILE))
1821
2778
  state = GIT_REPOSITORY_STATE_MERGE;
1822
- else if(git_path_contains_file(&repo_path, GIT_REVERT_HEAD_FILE))
2779
+ else if (git_path_contains_file(&repo_path, GIT_REVERT_HEAD_FILE)) {
1823
2780
  state = GIT_REPOSITORY_STATE_REVERT;
1824
- else if(git_path_contains_file(&repo_path, GIT_CHERRY_PICK_HEAD_FILE))
1825
- state = GIT_REPOSITORY_STATE_CHERRY_PICK;
1826
- else if(git_path_contains_file(&repo_path, GIT_BISECT_LOG_FILE))
2781
+ if (git_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
2782
+ state = GIT_REPOSITORY_STATE_REVERT_SEQUENCE;
2783
+ }
2784
+ } else if (git_path_contains_file(&repo_path, GIT_CHERRYPICK_HEAD_FILE)) {
2785
+ state = GIT_REPOSITORY_STATE_CHERRYPICK;
2786
+ if (git_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
2787
+ state = GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE;
2788
+ }
2789
+ } else if (git_path_contains_file(&repo_path, GIT_BISECT_LOG_FILE))
1827
2790
  state = GIT_REPOSITORY_STATE_BISECT;
1828
2791
 
1829
- git_buf_free(&repo_path);
2792
+ git_buf_dispose(&repo_path);
1830
2793
  return state;
1831
2794
  }
1832
2795
 
2796
+ int git_repository__cleanup_files(
2797
+ git_repository *repo, const char *files[], size_t files_len)
2798
+ {
2799
+ git_buf buf = GIT_BUF_INIT;
2800
+ size_t i;
2801
+ int error;
2802
+
2803
+ for (error = 0, i = 0; !error && i < files_len; ++i) {
2804
+ const char *path;
2805
+
2806
+ if (git_buf_joinpath(&buf, repo->gitdir, files[i]) < 0)
2807
+ return -1;
2808
+
2809
+ path = git_buf_cstr(&buf);
2810
+
2811
+ if (git_path_isfile(path)) {
2812
+ error = p_unlink(path);
2813
+ } else if (git_path_isdir(path)) {
2814
+ error = git_futils_rmdir_r(path, NULL,
2815
+ GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS);
2816
+ }
2817
+
2818
+ git_buf_clear(&buf);
2819
+ }
2820
+
2821
+ git_buf_dispose(&buf);
2822
+ return error;
2823
+ }
2824
+
2825
+ static const char *state_files[] = {
2826
+ GIT_MERGE_HEAD_FILE,
2827
+ GIT_MERGE_MODE_FILE,
2828
+ GIT_MERGE_MSG_FILE,
2829
+ GIT_REVERT_HEAD_FILE,
2830
+ GIT_CHERRYPICK_HEAD_FILE,
2831
+ GIT_BISECT_LOG_FILE,
2832
+ GIT_REBASE_MERGE_DIR,
2833
+ GIT_REBASE_APPLY_DIR,
2834
+ GIT_SEQUENCER_DIR,
2835
+ };
2836
+
2837
+ int git_repository_state_cleanup(git_repository *repo)
2838
+ {
2839
+ assert(repo);
2840
+
2841
+ return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
2842
+ }
2843
+
1833
2844
  int git_repository_is_shallow(git_repository *repo)
1834
2845
  {
1835
2846
  git_buf path = GIT_BUF_INIT;
1836
2847
  struct stat st;
1837
2848
  int error;
1838
2849
 
1839
- git_buf_joinpath(&path, repo->path_repository, "shallow");
2850
+ if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0)
2851
+ return error;
2852
+
1840
2853
  error = git_path_lstat(path.ptr, &st);
1841
- git_buf_free(&path);
2854
+ git_buf_dispose(&path);
1842
2855
 
1843
- if (error == GIT_ENOTFOUND)
2856
+ if (error == GIT_ENOTFOUND) {
2857
+ git_error_clear();
1844
2858
  return 0;
2859
+ }
2860
+
1845
2861
  if (error < 0)
1846
- return -1;
2862
+ return error;
1847
2863
  return st.st_size == 0 ? 0 : 1;
1848
2864
  }
2865
+
2866
+ int git_repository_init_init_options(
2867
+ git_repository_init_options *opts, unsigned int version)
2868
+ {
2869
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
2870
+ opts, version, git_repository_init_options,
2871
+ GIT_REPOSITORY_INIT_OPTIONS_INIT);
2872
+ return 0;
2873
+ }
2874
+
2875
+ int git_repository_ident(const char **name, const char **email, const git_repository *repo)
2876
+ {
2877
+ *name = repo->ident_name;
2878
+ *email = repo->ident_email;
2879
+
2880
+ return 0;
2881
+ }
2882
+
2883
+ int git_repository_set_ident(git_repository *repo, const char *name, const char *email)
2884
+ {
2885
+ char *tmp_name = NULL, *tmp_email = NULL;
2886
+
2887
+ if (name) {
2888
+ tmp_name = git__strdup(name);
2889
+ GIT_ERROR_CHECK_ALLOC(tmp_name);
2890
+ }
2891
+
2892
+ if (email) {
2893
+ tmp_email = git__strdup(email);
2894
+ GIT_ERROR_CHECK_ALLOC(tmp_email);
2895
+ }
2896
+
2897
+ tmp_name = git__swap(repo->ident_name, tmp_name);
2898
+ tmp_email = git__swap(repo->ident_email, tmp_email);
2899
+
2900
+ git__free(tmp_name);
2901
+ git__free(tmp_email);
2902
+
2903
+ return 0;
2904
+ }
2905
+
2906
+ int git_repository_submodule_cache_all(git_repository *repo)
2907
+ {
2908
+ int error;
2909
+
2910
+ assert(repo);
2911
+
2912
+ if ((error = git_strmap_alloc(&repo->submodule_cache)))
2913
+ return error;
2914
+
2915
+ error = git_submodule__map(repo, repo->submodule_cache);
2916
+ return error;
2917
+ }
2918
+
2919
+ int git_repository_submodule_cache_clear(git_repository *repo)
2920
+ {
2921
+ git_submodule *sm;
2922
+ assert(repo);
2923
+ if (repo->submodule_cache == NULL) {
2924
+ return 0;
2925
+ }
2926
+ git_strmap_foreach_value(repo->submodule_cache, sm, {
2927
+ git_submodule_free(sm);
2928
+ });
2929
+ git_strmap_free(repo->submodule_cache);
2930
+ repo->submodule_cache = 0;
2931
+ return 0;
2932
+ }