rugged 0.28.4.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/rugged/extconf.rb +3 -1
  4. data/ext/rugged/rugged.c +35 -31
  5. data/ext/rugged/rugged.h +13 -0
  6. data/ext/rugged/rugged_blob.c +11 -9
  7. data/ext/rugged/rugged_commit.c +17 -15
  8. data/ext/rugged/rugged_config.c +1 -1
  9. data/ext/rugged/rugged_diff.c +4 -26
  10. data/ext/rugged/rugged_index.c +4 -2
  11. data/ext/rugged/rugged_note.c +5 -3
  12. data/ext/rugged/rugged_object.c +57 -10
  13. data/ext/rugged/rugged_rebase.c +3 -1
  14. data/ext/rugged/rugged_remote.c +32 -8
  15. data/ext/rugged/rugged_repo.c +232 -17
  16. data/ext/rugged/rugged_tag.c +8 -6
  17. data/ext/rugged/rugged_tree.c +18 -16
  18. data/lib/rugged/commit.rb +1 -2
  19. data/lib/rugged/repository.rb +5 -6
  20. data/lib/rugged/submodule_collection.rb +4 -4
  21. data/lib/rugged/version.rb +1 -1
  22. data/vendor/libgit2/AUTHORS +1 -0
  23. data/vendor/libgit2/CMakeLists.txt +39 -19
  24. data/vendor/libgit2/COPYING +28 -0
  25. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +5 -1
  26. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +2 -2
  27. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +1 -1
  28. data/vendor/libgit2/cmake/Modules/FindGSSFramework.cmake +28 -0
  29. data/vendor/libgit2/cmake/Modules/FindPCRE.cmake +38 -0
  30. data/vendor/libgit2/cmake/Modules/FindPCRE2.cmake +37 -0
  31. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +2 -2
  32. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +6 -0
  33. data/vendor/libgit2/cmake/Modules/PkgBuildConfig.cmake +77 -0
  34. data/vendor/libgit2/cmake/Modules/SanitizeBool.cmake +20 -0
  35. data/vendor/libgit2/cmake/Modules/SelectGSSAPI.cmake +56 -0
  36. data/vendor/libgit2/cmake/Modules/SelectHTTPSBackend.cmake +127 -0
  37. data/vendor/libgit2/cmake/Modules/SelectHashes.cmake +69 -0
  38. data/vendor/libgit2/deps/http-parser/http_parser.c +11 -6
  39. data/vendor/libgit2/deps/ntlmclient/CMakeLists.txt +23 -0
  40. data/vendor/libgit2/deps/ntlmclient/compat.h +55 -0
  41. data/vendor/libgit2/deps/ntlmclient/crypt.h +64 -0
  42. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.c +120 -0
  43. data/vendor/libgit2/deps/ntlmclient/crypt_commoncrypto.h +18 -0
  44. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.c +145 -0
  45. data/vendor/libgit2/deps/ntlmclient/crypt_mbedtls.h +18 -0
  46. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.c +130 -0
  47. data/vendor/libgit2/deps/ntlmclient/crypt_openssl.h +21 -0
  48. data/vendor/libgit2/deps/ntlmclient/ntlm.c +1422 -0
  49. data/vendor/libgit2/deps/ntlmclient/ntlm.h +174 -0
  50. data/vendor/libgit2/deps/ntlmclient/ntlmclient.h +320 -0
  51. data/vendor/libgit2/deps/ntlmclient/unicode.h +36 -0
  52. data/vendor/libgit2/deps/ntlmclient/unicode_builtin.c +445 -0
  53. data/vendor/libgit2/deps/ntlmclient/unicode_iconv.c +201 -0
  54. data/vendor/libgit2/deps/ntlmclient/utf8.h +1257 -0
  55. data/vendor/libgit2/deps/ntlmclient/util.c +21 -0
  56. data/vendor/libgit2/deps/ntlmclient/util.h +14 -0
  57. data/vendor/libgit2/deps/pcre/CMakeLists.txt +140 -0
  58. data/vendor/libgit2/deps/pcre/COPYING +5 -0
  59. data/vendor/libgit2/deps/pcre/cmake/COPYING-CMAKE-SCRIPTS +22 -0
  60. data/vendor/libgit2/deps/pcre/cmake/FindEditline.cmake +17 -0
  61. data/vendor/libgit2/deps/pcre/cmake/FindPackageHandleStandardArgs.cmake +58 -0
  62. data/vendor/libgit2/deps/pcre/cmake/FindReadline.cmake +29 -0
  63. data/vendor/libgit2/deps/pcre/config.h.in +57 -0
  64. data/vendor/libgit2/deps/pcre/pcre.h +641 -0
  65. data/vendor/libgit2/deps/pcre/pcre_byte_order.c +319 -0
  66. data/vendor/libgit2/deps/pcre/pcre_chartables.c +198 -0
  67. data/vendor/libgit2/deps/pcre/pcre_compile.c +9800 -0
  68. data/vendor/libgit2/deps/pcre/pcre_config.c +190 -0
  69. data/vendor/libgit2/deps/pcre/pcre_dfa_exec.c +3676 -0
  70. data/vendor/libgit2/deps/pcre/pcre_exec.c +7173 -0
  71. data/vendor/libgit2/deps/pcre/pcre_fullinfo.c +245 -0
  72. data/vendor/libgit2/deps/pcre/pcre_get.c +669 -0
  73. data/vendor/libgit2/deps/pcre/pcre_globals.c +86 -0
  74. data/vendor/libgit2/deps/pcre/pcre_internal.h +2787 -0
  75. data/vendor/libgit2/deps/pcre/pcre_jit_compile.c +11913 -0
  76. data/vendor/libgit2/deps/pcre/pcre_maketables.c +156 -0
  77. data/vendor/libgit2/deps/pcre/pcre_newline.c +210 -0
  78. data/vendor/libgit2/deps/pcre/pcre_ord2utf8.c +94 -0
  79. data/vendor/libgit2/deps/pcre/pcre_printint.c +834 -0
  80. data/vendor/libgit2/deps/pcre/pcre_refcount.c +92 -0
  81. data/vendor/libgit2/deps/pcre/pcre_string_utils.c +211 -0
  82. data/vendor/libgit2/deps/pcre/pcre_study.c +1686 -0
  83. data/vendor/libgit2/deps/pcre/pcre_tables.c +727 -0
  84. data/vendor/libgit2/deps/pcre/pcre_ucd.c +3644 -0
  85. data/vendor/libgit2/deps/pcre/pcre_valid_utf8.c +301 -0
  86. data/vendor/libgit2/deps/pcre/pcre_version.c +98 -0
  87. data/vendor/libgit2/deps/pcre/pcre_xclass.c +268 -0
  88. data/vendor/libgit2/deps/pcre/pcreposix.c +421 -0
  89. data/vendor/libgit2/deps/pcre/pcreposix.h +117 -0
  90. data/vendor/libgit2/deps/pcre/ucp.h +224 -0
  91. data/vendor/libgit2/deps/zlib/adler32.c +0 -7
  92. data/vendor/libgit2/deps/zlib/crc32.c +0 -7
  93. data/vendor/libgit2/include/git2.h +2 -0
  94. data/vendor/libgit2/include/git2/apply.h +22 -2
  95. data/vendor/libgit2/include/git2/attr.h +23 -13
  96. data/vendor/libgit2/include/git2/blame.h +2 -2
  97. data/vendor/libgit2/include/git2/blob.h +44 -12
  98. data/vendor/libgit2/include/git2/branch.h +74 -57
  99. data/vendor/libgit2/include/git2/buffer.h +20 -14
  100. data/vendor/libgit2/include/git2/cert.h +135 -0
  101. data/vendor/libgit2/include/git2/checkout.h +46 -14
  102. data/vendor/libgit2/include/git2/cherrypick.h +3 -3
  103. data/vendor/libgit2/include/git2/clone.h +2 -2
  104. data/vendor/libgit2/include/git2/commit.h +23 -1
  105. data/vendor/libgit2/include/git2/common.h +15 -6
  106. data/vendor/libgit2/include/git2/config.h +12 -12
  107. data/vendor/libgit2/include/git2/cred_helpers.h +4 -42
  108. data/vendor/libgit2/include/git2/credential.h +314 -0
  109. data/vendor/libgit2/include/git2/credential_helpers.h +52 -0
  110. data/vendor/libgit2/include/git2/deprecated.h +321 -3
  111. data/vendor/libgit2/include/git2/describe.h +4 -4
  112. data/vendor/libgit2/include/git2/diff.h +16 -14
  113. data/vendor/libgit2/include/git2/errors.h +4 -2
  114. data/vendor/libgit2/include/git2/filter.h +8 -0
  115. data/vendor/libgit2/include/git2/index.h +2 -1
  116. data/vendor/libgit2/include/git2/indexer.h +48 -4
  117. data/vendor/libgit2/include/git2/merge.h +6 -10
  118. data/vendor/libgit2/include/git2/net.h +0 -5
  119. data/vendor/libgit2/include/git2/object.h +2 -14
  120. data/vendor/libgit2/include/git2/odb.h +3 -2
  121. data/vendor/libgit2/include/git2/odb_backend.h +5 -4
  122. data/vendor/libgit2/include/git2/oid.h +11 -6
  123. data/vendor/libgit2/include/git2/pack.h +12 -1
  124. data/vendor/libgit2/include/git2/proxy.h +6 -4
  125. data/vendor/libgit2/include/git2/rebase.h +46 -2
  126. data/vendor/libgit2/include/git2/refs.h +19 -0
  127. data/vendor/libgit2/include/git2/remote.h +40 -15
  128. data/vendor/libgit2/include/git2/repository.h +29 -6
  129. data/vendor/libgit2/include/git2/revert.h +1 -1
  130. data/vendor/libgit2/include/git2/revwalk.h +7 -3
  131. data/vendor/libgit2/include/git2/stash.h +4 -4
  132. data/vendor/libgit2/include/git2/status.h +25 -16
  133. data/vendor/libgit2/include/git2/submodule.h +20 -3
  134. data/vendor/libgit2/include/git2/sys/alloc.h +9 -9
  135. data/vendor/libgit2/include/git2/sys/cred.h +15 -0
  136. data/vendor/libgit2/include/git2/sys/credential.h +90 -0
  137. data/vendor/libgit2/include/git2/sys/index.h +4 -2
  138. data/vendor/libgit2/include/git2/sys/mempack.h +2 -1
  139. data/vendor/libgit2/include/git2/sys/merge.h +1 -1
  140. data/vendor/libgit2/include/git2/sys/odb_backend.h +48 -4
  141. data/vendor/libgit2/include/git2/sys/refdb_backend.h +164 -21
  142. data/vendor/libgit2/include/git2/sys/repository.h +17 -6
  143. data/vendor/libgit2/include/git2/sys/transport.h +4 -4
  144. data/vendor/libgit2/include/git2/tag.h +11 -2
  145. data/vendor/libgit2/include/git2/trace.h +2 -2
  146. data/vendor/libgit2/include/git2/transport.h +11 -340
  147. data/vendor/libgit2/include/git2/tree.h +5 -3
  148. data/vendor/libgit2/include/git2/types.h +4 -89
  149. data/vendor/libgit2/include/git2/version.h +5 -5
  150. data/vendor/libgit2/include/git2/worktree.h +5 -5
  151. data/vendor/libgit2/src/CMakeLists.txt +99 -236
  152. data/vendor/libgit2/src/alloc.c +2 -14
  153. data/vendor/libgit2/src/{stdalloc.c → allocators/stdalloc.c} +3 -4
  154. data/vendor/libgit2/src/{stdalloc.h → allocators/stdalloc.h} +4 -4
  155. data/vendor/libgit2/src/allocators/win32_crtdbg.c +118 -0
  156. data/vendor/libgit2/src/{transports/cred.h → allocators/win32_crtdbg.h} +5 -4
  157. data/vendor/libgit2/src/apply.c +60 -30
  158. data/vendor/libgit2/src/attr.c +70 -64
  159. data/vendor/libgit2/src/attr_file.c +189 -96
  160. data/vendor/libgit2/src/attr_file.h +9 -9
  161. data/vendor/libgit2/src/attrcache.c +48 -48
  162. data/vendor/libgit2/src/attrcache.h +2 -1
  163. data/vendor/libgit2/src/blame.c +17 -5
  164. data/vendor/libgit2/src/blame.h +1 -1
  165. data/vendor/libgit2/src/blame_git.c +21 -7
  166. data/vendor/libgit2/src/blob.c +81 -17
  167. data/vendor/libgit2/src/blob.h +2 -2
  168. data/vendor/libgit2/src/branch.c +60 -32
  169. data/vendor/libgit2/src/buffer.c +19 -7
  170. data/vendor/libgit2/src/buffer.h +1 -0
  171. data/vendor/libgit2/src/cache.c +33 -36
  172. data/vendor/libgit2/src/cache.h +1 -1
  173. data/vendor/libgit2/src/cc-compat.h +5 -0
  174. data/vendor/libgit2/src/checkout.c +26 -16
  175. data/vendor/libgit2/src/cherrypick.c +9 -3
  176. data/vendor/libgit2/src/clone.c +29 -7
  177. data/vendor/libgit2/src/clone.h +4 -0
  178. data/vendor/libgit2/src/commit.c +70 -22
  179. data/vendor/libgit2/src/commit.h +6 -0
  180. data/vendor/libgit2/src/commit_list.c +28 -76
  181. data/vendor/libgit2/src/commit_list.h +2 -2
  182. data/vendor/libgit2/src/common.h +3 -75
  183. data/vendor/libgit2/src/config.c +31 -40
  184. data/vendor/libgit2/src/config.h +7 -6
  185. data/vendor/libgit2/src/config_backend.h +12 -0
  186. data/vendor/libgit2/src/config_cache.c +39 -39
  187. data/vendor/libgit2/src/config_entries.c +69 -99
  188. data/vendor/libgit2/src/config_entries.h +1 -0
  189. data/vendor/libgit2/src/config_file.c +346 -380
  190. data/vendor/libgit2/src/config_mem.c +12 -16
  191. data/vendor/libgit2/src/config_parse.c +49 -29
  192. data/vendor/libgit2/src/config_parse.h +13 -12
  193. data/vendor/libgit2/src/config_snapshot.c +206 -0
  194. data/vendor/libgit2/src/crlf.c +14 -14
  195. data/vendor/libgit2/src/describe.c +21 -20
  196. data/vendor/libgit2/src/diff.c +43 -58
  197. data/vendor/libgit2/src/diff.h +4 -3
  198. data/vendor/libgit2/src/diff_driver.c +37 -38
  199. data/vendor/libgit2/src/diff_file.c +12 -10
  200. data/vendor/libgit2/src/diff_file.h +2 -2
  201. data/vendor/libgit2/src/diff_generate.c +148 -98
  202. data/vendor/libgit2/src/diff_generate.h +2 -2
  203. data/vendor/libgit2/src/diff_parse.c +1 -1
  204. data/vendor/libgit2/src/diff_print.c +25 -13
  205. data/vendor/libgit2/src/diff_stats.c +1 -1
  206. data/vendor/libgit2/src/diff_tform.c +11 -11
  207. data/vendor/libgit2/src/errors.c +21 -25
  208. data/vendor/libgit2/src/errors.h +81 -0
  209. data/vendor/libgit2/src/features.h.in +9 -2
  210. data/vendor/libgit2/src/fetch.c +7 -2
  211. data/vendor/libgit2/src/fetchhead.c +36 -4
  212. data/vendor/libgit2/src/filebuf.c +6 -10
  213. data/vendor/libgit2/src/filebuf.h +2 -2
  214. data/vendor/libgit2/src/filter.c +16 -8
  215. data/vendor/libgit2/src/{fileops.c → futils.c} +21 -17
  216. data/vendor/libgit2/src/{fileops.h → futils.h} +5 -5
  217. data/vendor/libgit2/src/global.c +12 -40
  218. data/vendor/libgit2/src/global.h +0 -2
  219. data/vendor/libgit2/src/hash.c +61 -0
  220. data/vendor/libgit2/src/hash.h +19 -21
  221. data/vendor/libgit2/src/hash/sha1.h +38 -0
  222. data/vendor/libgit2/src/hash/{hash_collisiondetect.h → sha1/collisiondetect.c} +14 -17
  223. data/vendor/libgit2/src/{sha1_lookup.h → hash/sha1/collisiondetect.h} +8 -8
  224. data/vendor/libgit2/src/hash/{hash_common_crypto.h → sha1/common_crypto.c} +15 -19
  225. data/vendor/libgit2/src/hash/sha1/common_crypto.h +19 -0
  226. data/vendor/libgit2/src/hash/{hash_generic.c → sha1/generic.c} +22 -10
  227. data/vendor/libgit2/src/hash/{hash_generic.h → sha1/generic.h} +4 -14
  228. data/vendor/libgit2/src/hash/{hash_mbedtls.c → sha1/mbedtls.c} +15 -7
  229. data/vendor/libgit2/src/hash/{hash_mbedtls.h → sha1/mbedtls.h} +6 -11
  230. data/vendor/libgit2/src/hash/{hash_openssl.h → sha1/openssl.c} +14 -18
  231. data/vendor/libgit2/src/hash/sha1/openssl.h +19 -0
  232. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.c +14 -3
  233. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/sha1.h +0 -0
  234. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/ubc_check.c +0 -0
  235. data/vendor/libgit2/src/hash/{sha1dc → sha1/sha1dc}/ubc_check.h +0 -0
  236. data/vendor/libgit2/src/hash/{hash_win32.c → sha1/win32.c} +34 -24
  237. data/vendor/libgit2/src/hash/{hash_win32.h → sha1/win32.h} +6 -19
  238. data/vendor/libgit2/src/hashsig.c +1 -1
  239. data/vendor/libgit2/src/idxmap.c +91 -65
  240. data/vendor/libgit2/src/idxmap.h +151 -15
  241. data/vendor/libgit2/src/ignore.c +32 -38
  242. data/vendor/libgit2/src/index.c +105 -83
  243. data/vendor/libgit2/src/index.h +1 -1
  244. data/vendor/libgit2/src/indexer.c +71 -72
  245. data/vendor/libgit2/src/integer.h +39 -4
  246. data/vendor/libgit2/src/iterator.c +40 -35
  247. data/vendor/libgit2/src/iterator.h +8 -8
  248. data/vendor/libgit2/src/map.h +1 -1
  249. data/vendor/libgit2/src/merge.c +78 -51
  250. data/vendor/libgit2/src/merge.h +2 -2
  251. data/vendor/libgit2/src/merge_driver.c +5 -5
  252. data/vendor/libgit2/src/merge_file.c +1 -1
  253. data/vendor/libgit2/src/mwindow.c +18 -23
  254. data/vendor/libgit2/src/mwindow.h +4 -4
  255. data/vendor/libgit2/src/net.c +411 -0
  256. data/vendor/libgit2/src/net.h +57 -0
  257. data/vendor/libgit2/src/netops.c +6 -193
  258. data/vendor/libgit2/src/netops.h +1 -34
  259. data/vendor/libgit2/src/notes.c +8 -5
  260. data/vendor/libgit2/src/object.c +3 -3
  261. data/vendor/libgit2/src/object.h +2 -0
  262. data/vendor/libgit2/src/odb.c +41 -23
  263. data/vendor/libgit2/src/odb.h +3 -2
  264. data/vendor/libgit2/src/odb_loose.c +17 -10
  265. data/vendor/libgit2/src/odb_mempack.c +13 -24
  266. data/vendor/libgit2/src/odb_pack.c +4 -5
  267. data/vendor/libgit2/src/offmap.c +43 -55
  268. data/vendor/libgit2/src/offmap.h +102 -24
  269. data/vendor/libgit2/src/oid.c +19 -8
  270. data/vendor/libgit2/src/oidmap.c +39 -57
  271. data/vendor/libgit2/src/oidmap.h +99 -19
  272. data/vendor/libgit2/src/pack-objects.c +28 -33
  273. data/vendor/libgit2/src/pack-objects.h +1 -1
  274. data/vendor/libgit2/src/pack.c +117 -129
  275. data/vendor/libgit2/src/pack.h +15 -18
  276. data/vendor/libgit2/src/parse.c +10 -0
  277. data/vendor/libgit2/src/parse.h +3 -3
  278. data/vendor/libgit2/src/patch.c +1 -1
  279. data/vendor/libgit2/src/patch_generate.c +2 -2
  280. data/vendor/libgit2/src/patch_parse.c +130 -33
  281. data/vendor/libgit2/src/path.c +43 -6
  282. data/vendor/libgit2/src/path.h +2 -0
  283. data/vendor/libgit2/src/pathspec.c +14 -14
  284. data/vendor/libgit2/src/pool.c +26 -22
  285. data/vendor/libgit2/src/pool.h +7 -7
  286. data/vendor/libgit2/src/posix.c +7 -7
  287. data/vendor/libgit2/src/posix.h +12 -1
  288. data/vendor/libgit2/src/proxy.c +7 -2
  289. data/vendor/libgit2/src/push.c +13 -7
  290. data/vendor/libgit2/src/reader.c +2 -2
  291. data/vendor/libgit2/src/rebase.c +87 -28
  292. data/vendor/libgit2/src/refdb.c +12 -0
  293. data/vendor/libgit2/src/refdb_fs.c +219 -167
  294. data/vendor/libgit2/src/reflog.c +11 -13
  295. data/vendor/libgit2/src/refs.c +39 -23
  296. data/vendor/libgit2/src/refs.h +8 -1
  297. data/vendor/libgit2/src/refspec.c +9 -16
  298. data/vendor/libgit2/src/regexp.c +221 -0
  299. data/vendor/libgit2/src/regexp.h +97 -0
  300. data/vendor/libgit2/src/remote.c +57 -55
  301. data/vendor/libgit2/src/remote.h +2 -2
  302. data/vendor/libgit2/src/repository.c +187 -154
  303. data/vendor/libgit2/src/repository.h +49 -40
  304. data/vendor/libgit2/src/revert.c +8 -3
  305. data/vendor/libgit2/src/revparse.c +18 -19
  306. data/vendor/libgit2/src/revwalk.c +72 -34
  307. data/vendor/libgit2/src/revwalk.h +20 -0
  308. data/vendor/libgit2/src/settings.c +13 -1
  309. data/vendor/libgit2/src/sortedcache.c +12 -26
  310. data/vendor/libgit2/src/sortedcache.h +1 -1
  311. data/vendor/libgit2/src/stash.c +47 -67
  312. data/vendor/libgit2/src/status.c +17 -11
  313. data/vendor/libgit2/src/streams/openssl.c +54 -2
  314. data/vendor/libgit2/src/streams/socket.c +2 -2
  315. data/vendor/libgit2/src/strmap.c +37 -84
  316. data/vendor/libgit2/src/strmap.h +105 -33
  317. data/vendor/libgit2/src/submodule.c +151 -126
  318. data/vendor/libgit2/src/submodule.h +1 -1
  319. data/vendor/libgit2/src/sysdir.c +11 -1
  320. data/vendor/libgit2/src/tag.c +10 -2
  321. data/vendor/libgit2/src/trace.c +1 -1
  322. data/vendor/libgit2/src/trace.h +3 -3
  323. data/vendor/libgit2/src/trailer.c +46 -32
  324. data/vendor/libgit2/src/transaction.c +10 -9
  325. data/vendor/libgit2/src/transports/auth.c +16 -15
  326. data/vendor/libgit2/src/transports/auth.h +18 -11
  327. data/vendor/libgit2/src/transports/auth_negotiate.c +64 -33
  328. data/vendor/libgit2/src/transports/auth_negotiate.h +2 -2
  329. data/vendor/libgit2/src/transports/auth_ntlm.c +223 -0
  330. data/vendor/libgit2/src/transports/auth_ntlm.h +38 -0
  331. data/vendor/libgit2/src/transports/credential.c +476 -0
  332. data/vendor/libgit2/src/transports/{cred_helpers.c → credential_helpers.c} +21 -8
  333. data/vendor/libgit2/src/transports/git.c +11 -16
  334. data/vendor/libgit2/src/transports/http.c +488 -1248
  335. data/vendor/libgit2/src/transports/http.h +4 -1
  336. data/vendor/libgit2/src/transports/httpclient.c +1549 -0
  337. data/vendor/libgit2/src/transports/httpclient.h +190 -0
  338. data/vendor/libgit2/src/transports/local.c +10 -10
  339. data/vendor/libgit2/src/transports/smart.c +19 -19
  340. data/vendor/libgit2/src/transports/smart.h +3 -3
  341. data/vendor/libgit2/src/transports/smart_pkt.c +1 -1
  342. data/vendor/libgit2/src/transports/smart_protocol.c +40 -64
  343. data/vendor/libgit2/src/transports/ssh.c +77 -59
  344. data/vendor/libgit2/src/transports/winhttp.c +272 -242
  345. data/vendor/libgit2/src/tree-cache.c +14 -7
  346. data/vendor/libgit2/src/tree.c +16 -26
  347. data/vendor/libgit2/src/unix/map.c +1 -1
  348. data/vendor/libgit2/src/unix/posix.h +2 -12
  349. data/vendor/libgit2/src/userdiff.h +3 -1
  350. data/vendor/libgit2/src/util.c +51 -53
  351. data/vendor/libgit2/src/util.h +16 -21
  352. data/vendor/libgit2/src/wildmatch.c +320 -0
  353. data/vendor/libgit2/src/wildmatch.h +23 -0
  354. data/vendor/libgit2/src/win32/map.c +3 -5
  355. data/vendor/libgit2/src/win32/path_w32.c +40 -3
  356. data/vendor/libgit2/src/win32/path_w32.h +15 -29
  357. data/vendor/libgit2/src/win32/posix.h +1 -4
  358. data/vendor/libgit2/src/win32/posix_w32.c +47 -5
  359. data/vendor/libgit2/src/win32/precompiled.h +0 -2
  360. data/vendor/libgit2/src/win32/thread.c +5 -10
  361. data/vendor/libgit2/src/win32/w32_buffer.c +7 -3
  362. data/vendor/libgit2/src/win32/w32_common.h +39 -0
  363. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +0 -93
  364. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +0 -2
  365. data/vendor/libgit2/src/win32/w32_stack.c +4 -9
  366. data/vendor/libgit2/src/win32/w32_stack.h +3 -3
  367. data/vendor/libgit2/src/win32/w32_util.c +31 -0
  368. data/vendor/libgit2/src/win32/w32_util.h +6 -32
  369. data/vendor/libgit2/src/worktree.c +79 -49
  370. data/vendor/libgit2/src/xdiff/xdiffi.c +1 -1
  371. data/vendor/libgit2/src/xdiff/xmerge.c +12 -0
  372. data/vendor/libgit2/src/xdiff/xpatience.c +3 -0
  373. data/vendor/libgit2/src/zstream.c +5 -0
  374. data/vendor/libgit2/src/zstream.h +1 -0
  375. metadata +108 -41
  376. data/vendor/libgit2/deps/regex/CMakeLists.txt +0 -2
  377. data/vendor/libgit2/deps/regex/COPYING +0 -502
  378. data/vendor/libgit2/deps/regex/config.h +0 -7
  379. data/vendor/libgit2/deps/regex/regcomp.c +0 -3857
  380. data/vendor/libgit2/deps/regex/regex.c +0 -92
  381. data/vendor/libgit2/deps/regex/regex.h +0 -582
  382. data/vendor/libgit2/deps/regex/regex_internal.c +0 -1744
  383. data/vendor/libgit2/deps/regex/regex_internal.h +0 -819
  384. data/vendor/libgit2/deps/regex/regexec.c +0 -4369
  385. data/vendor/libgit2/include/git2/inttypes.h +0 -309
  386. data/vendor/libgit2/include/git2/sys/time.h +0 -31
  387. data/vendor/libgit2/libgit2.pc.in +0 -13
  388. data/vendor/libgit2/src/fnmatch.c +0 -248
  389. data/vendor/libgit2/src/fnmatch.h +0 -48
  390. data/vendor/libgit2/src/sha1_lookup.c +0 -35
  391. data/vendor/libgit2/src/transports/cred.c +0 -390
@@ -11,6 +11,7 @@ typedef struct config_entry_list {
11
11
  struct config_entry_list *next;
12
12
  struct config_entry_list *last;
13
13
  git_config_entry *entry;
14
+ bool first;
14
15
  } config_entry_list;
15
16
 
16
17
  typedef struct config_entries_iterator {
@@ -25,31 +26,6 @@ struct git_config_entries {
25
26
  config_entry_list *list;
26
27
  };
27
28
 
28
- static void config_entry_list_free(config_entry_list *list)
29
- {
30
- config_entry_list *next;
31
-
32
- while (list != NULL) {
33
- next = list->next;
34
-
35
- git__free((char*) list->entry->name);
36
- git__free((char *) list->entry->value);
37
- git__free(list->entry);
38
- git__free(list);
39
-
40
- list = next;
41
- };
42
- }
43
-
44
- static void config_entry_list_append(config_entry_list **list, config_entry_list *entry)
45
- {
46
- if (*list)
47
- (*list)->last->next = entry;
48
- else
49
- *list = entry;
50
- (*list)->last = entry;
51
- }
52
-
53
29
  int git_config_entries_new(git_config_entries **out)
54
30
  {
55
31
  git_config_entries *entries;
@@ -59,7 +35,7 @@ int git_config_entries_new(git_config_entries **out)
59
35
  GIT_ERROR_CHECK_ALLOC(entries);
60
36
  GIT_REFCOUNT_INC(entries);
61
37
 
62
- if ((error = git_strmap_alloc(&entries->map)) < 0)
38
+ if ((error = git_strmap_new(&entries->map)) < 0)
63
39
  git__free(entries);
64
40
  else
65
41
  *out = entries;
@@ -67,6 +43,36 @@ int git_config_entries_new(git_config_entries **out)
67
43
  return error;
68
44
  }
69
45
 
46
+ int git_config_entries_dup_entry(git_config_entries *entries, const git_config_entry *entry)
47
+ {
48
+ git_config_entry *duplicated;
49
+ int error;
50
+
51
+ duplicated = git__calloc(1, sizeof(git_config_entry));
52
+ GIT_ERROR_CHECK_ALLOC(duplicated);
53
+
54
+ duplicated->name = git__strdup(entry->name);
55
+ GIT_ERROR_CHECK_ALLOC(duplicated->name);
56
+
57
+ if (entry->value) {
58
+ duplicated->value = git__strdup(entry->value);
59
+ GIT_ERROR_CHECK_ALLOC(duplicated->value);
60
+ }
61
+ duplicated->level = entry->level;
62
+ duplicated->include_depth = entry->include_depth;
63
+
64
+ if ((error = git_config_entries_append(entries, duplicated)) < 0)
65
+ goto out;
66
+
67
+ out:
68
+ if (error && duplicated) {
69
+ git__free((char *) duplicated->name);
70
+ git__free((char *) duplicated->value);
71
+ git__free(duplicated);
72
+ }
73
+ return error;
74
+ }
75
+
70
76
  int git_config_entries_dup(git_config_entries **out, git_config_entries *entries)
71
77
  {
72
78
  git_config_entries *result = NULL;
@@ -76,22 +82,9 @@ int git_config_entries_dup(git_config_entries **out, git_config_entries *entries
76
82
  if ((error = git_config_entries_new(&result)) < 0)
77
83
  goto out;
78
84
 
79
- for (head = entries->list; head; head = head->next) {
80
- git_config_entry *dup;
81
-
82
- dup = git__calloc(1, sizeof(git_config_entry));
83
- dup->name = git__strdup(head->entry->name);
84
- GIT_ERROR_CHECK_ALLOC(dup->name);
85
- if (head->entry->value) {
86
- dup->value = git__strdup(head->entry->value);
87
- GIT_ERROR_CHECK_ALLOC(dup->value);
88
- }
89
- dup->level = head->entry->level;
90
- dup->include_depth = head->entry->include_depth;
91
-
92
- if ((error = git_config_entries_append(result, dup)) < 0)
85
+ for (head = entries->list; head; head = head->next)
86
+ if ((git_config_entries_dup_entry(result, head->entry)) < 0)
93
87
  goto out;
94
- }
95
88
 
96
89
  *out = result;
97
90
  result = NULL;
@@ -110,12 +103,15 @@ static void config_entries_free(git_config_entries *entries)
110
103
  {
111
104
  config_entry_list *list = NULL, *next;
112
105
 
113
- git_strmap_foreach_value(entries->map, list, config_entry_list_free(list));
114
106
  git_strmap_free(entries->map);
115
107
 
116
108
  list = entries->list;
117
109
  while (list != NULL) {
118
110
  next = list->next;
111
+ if (list->first)
112
+ git__free((char *) list->entry->name);
113
+ git__free((char *) list->entry->value);
114
+ git__free(list->entry);
119
115
  git__free(list);
120
116
  list = next;
121
117
  }
@@ -131,55 +127,33 @@ void git_config_entries_free(git_config_entries *entries)
131
127
 
132
128
  int git_config_entries_append(git_config_entries *entries, git_config_entry *entry)
133
129
  {
134
- config_entry_list *existing, *var;
135
- int error = 0;
136
- size_t pos;
137
-
138
- var = git__calloc(1, sizeof(config_entry_list));
139
- GIT_ERROR_CHECK_ALLOC(var);
140
- var->entry = entry;
141
-
142
- pos = git_strmap_lookup_index(entries->map, entry->name);
143
- if (!git_strmap_valid_index(entries->map, pos)) {
144
- /*
145
- * We only ever inspect `last` from the first config
146
- * entry in a multivar. In case where this new entry is
147
- * the first one in the entry map, it will also be the
148
- * last one at the time of adding it, which is
149
- * why we set `last` here to itself. Otherwise we
150
- * do not have to set `last` and leave it set to
151
- * `NULL`.
152
- */
153
- var->last = var;
154
-
155
- git_strmap_insert(entries->map, entry->name, var, &error);
156
-
157
- if (error > 0)
158
- error = 0;
130
+ config_entry_list *existing, *head;
131
+
132
+ head = git__calloc(1, sizeof(config_entry_list));
133
+ GIT_ERROR_CHECK_ALLOC(head);
134
+ head->entry = entry;
135
+
136
+ /*
137
+ * This is a micro-optimization for configuration files
138
+ * with a lot of same keys. As for multivars the entry's
139
+ * key will be the same for all entries, we can just free
140
+ * all except the first entry's name and just re-use it.
141
+ */
142
+ if ((existing = git_strmap_get(entries->map, entry->name)) != NULL) {
143
+ git__free((char *) entry->name);
144
+ entry->name = existing->entry->name;
159
145
  } else {
160
- existing = git_strmap_value_at(entries->map, pos);
161
- config_entry_list_append(&existing, var);
146
+ head->first = 1;
162
147
  }
163
148
 
164
- var = git__calloc(1, sizeof(config_entry_list));
165
- GIT_ERROR_CHECK_ALLOC(var);
166
- var->entry = entry;
167
- config_entry_list_append(&entries->list, var);
168
-
169
- return error;
170
- }
171
-
172
- int config_entry_get(config_entry_list **out, git_config_entries *entries, const char *key)
173
- {
174
- size_t pos;
175
-
176
- pos = git_strmap_lookup_index(entries->map, key);
177
-
178
- /* no error message; the config system will write one */
179
- if (!git_strmap_valid_index(entries->map, pos))
180
- return GIT_ENOTFOUND;
149
+ if (entries->list)
150
+ entries->list->last->next = head;
151
+ else
152
+ entries->list = head;
153
+ entries->list->last = head;
181
154
 
182
- *out = git_strmap_value_at(entries->map, pos);
155
+ if (git_strmap_set(entries->map, entry->name, head) < 0)
156
+ return -1;
183
157
 
184
158
  return 0;
185
159
  }
@@ -187,24 +161,20 @@ int config_entry_get(config_entry_list **out, git_config_entries *entries, const
187
161
  int git_config_entries_get(git_config_entry **out, git_config_entries *entries, const char *key)
188
162
  {
189
163
  config_entry_list *entry;
190
- int error;
191
-
192
- if ((error = config_entry_get(&entry, entries, key)) < 0)
193
- return error;
194
- *out = entry->last->entry;
195
-
164
+ if ((entry = git_strmap_get(entries->map, key)) == NULL)
165
+ return GIT_ENOTFOUND;
166
+ *out = entry->entry;
196
167
  return 0;
197
168
  }
198
169
 
199
170
  int git_config_entries_get_unique(git_config_entry **out, git_config_entries *entries, const char *key)
200
171
  {
201
172
  config_entry_list *entry;
202
- int error;
203
173
 
204
- if ((error = config_entry_get(&entry, entries, key)) < 0)
205
- return error;
174
+ if ((entry = git_strmap_get(entries->map, key)) == NULL)
175
+ return GIT_ENOTFOUND;
206
176
 
207
- if (entry->next != NULL) {
177
+ if (!entry->first) {
208
178
  git_error_set(GIT_ERROR_CONFIG, "entry is not unique due to being a multivar");
209
179
  return -1;
210
180
  }
@@ -219,14 +189,14 @@ int git_config_entries_get_unique(git_config_entry **out, git_config_entries *en
219
189
  return 0;
220
190
  }
221
191
 
222
- void config_iterator_free(git_config_iterator *iter)
192
+ static void config_iterator_free(git_config_iterator *iter)
223
193
  {
224
194
  config_entries_iterator *it = (config_entries_iterator *) iter;
225
195
  git_config_entries_free(it->entries);
226
196
  git__free(it);
227
197
  }
228
198
 
229
- int config_iterator_next(
199
+ static int config_iterator_next(
230
200
  git_config_entry **entry,
231
201
  git_config_iterator *iter)
232
202
  {
@@ -14,6 +14,7 @@ typedef struct git_config_entries git_config_entries;
14
14
 
15
15
  int git_config_entries_new(git_config_entries **out);
16
16
  int git_config_entries_dup(git_config_entries **out, git_config_entries *entries);
17
+ int git_config_entries_dup_entry(git_config_entries *entries, const git_config_entry *entry);
17
18
  void git_config_entries_incref(git_config_entries *entries);
18
19
  void git_config_entries_free(git_config_entries *entries);
19
20
  /* Add or append the new config option */
@@ -7,36 +7,35 @@
7
7
 
8
8
  #include "config.h"
9
9
 
10
- #include "filebuf.h"
11
- #include "sysdir.h"
12
- #include "buffer.h"
13
- #include "buf_text.h"
14
10
  #include "git2/config.h"
15
11
  #include "git2/sys/config.h"
16
- #include "git2/types.h"
17
- #include "strmap.h"
12
+
18
13
  #include "array.h"
19
- #include "config_parse.h"
14
+ #include "buffer.h"
15
+ #include "config_backend.h"
20
16
  #include "config_entries.h"
21
-
22
- #include <ctype.h>
23
- #include <sys/types.h>
24
- #include <regex.h>
17
+ #include "config_parse.h"
18
+ #include "filebuf.h"
19
+ #include "regexp.h"
20
+ #include "sysdir.h"
21
+ #include "wildmatch.h"
25
22
 
26
23
  /* Max depth for [include] directives */
27
24
  #define MAX_INCLUDE_DEPTH 10
28
25
 
26
+ typedef struct config_file {
27
+ git_futils_filestamp stamp;
28
+ git_oid checksum;
29
+ char *path;
30
+ git_array_t(struct config_file) includes;
31
+ } config_file;
32
+
29
33
  typedef struct {
30
34
  git_config_backend parent;
31
- /* mutex to coordinate accessing the values */
32
35
  git_mutex values_mutex;
33
36
  git_config_entries *entries;
34
37
  const git_repository *repo;
35
38
  git_config_level_t level;
36
- } diskfile_header;
37
-
38
- typedef struct {
39
- diskfile_header header;
40
39
 
41
40
  git_array_t(git_config_parser) readers;
42
41
 
@@ -44,60 +43,47 @@ typedef struct {
44
43
  git_filebuf locked_buf;
45
44
  git_buf locked_content;
46
45
 
47
- struct config_file file;
48
- } diskfile_backend;
49
-
50
- typedef struct {
51
- diskfile_header header;
52
-
53
- diskfile_backend *snapshot_from;
54
- } diskfile_readonly_backend;
46
+ config_file file;
47
+ } config_file_backend;
55
48
 
56
49
  typedef struct {
57
50
  const git_repository *repo;
58
- const char *file_path;
51
+ config_file *file;
59
52
  git_config_entries *entries;
60
53
  git_config_level_t level;
61
54
  unsigned int depth;
62
- } diskfile_parse_state;
55
+ } config_file_parse_data;
63
56
 
64
- static int config_read(git_config_entries *entries, const git_repository *repo, git_config_file *file, git_config_level_t level, int depth);
65
- static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char *value);
57
+ static int config_file_read(git_config_entries *entries, const git_repository *repo, config_file *file, git_config_level_t level, int depth);
58
+ static int config_file_read_buffer(git_config_entries *entries, const git_repository *repo, config_file *file, git_config_level_t level, int depth, const char *buf, size_t buflen);
59
+ static int config_file_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char *value);
66
60
  static char *escape_value(const char *ptr);
67
61
 
68
- static int config_snapshot(git_config_backend **out, git_config_backend *in);
69
-
70
- static int config_error_readonly(void)
71
- {
72
- git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
73
- return -1;
74
- }
75
-
76
62
  /**
77
63
  * Take the current values map from the backend and increase its
78
64
  * refcount. This is its own function to make sure we use the mutex to
79
65
  * avoid the map pointer from changing under us.
80
66
  */
81
- static git_config_entries *diskfile_entries_take(diskfile_header *h)
67
+ static int config_file_entries_take(git_config_entries **out, config_file_backend *b)
82
68
  {
83
- git_config_entries *entries;
69
+ int error;
84
70
 
85
- if (git_mutex_lock(&h->values_mutex) < 0) {
86
- git_error_set(GIT_ERROR_OS, "failed to lock config backend");
87
- return NULL;
71
+ if ((error = git_mutex_lock(&b->values_mutex)) < 0) {
72
+ git_error_set(GIT_ERROR_OS, "failed to lock config backend");
73
+ return error;
88
74
  }
89
75
 
90
- entries = h->entries;
91
- git_config_entries_incref(entries);
76
+ git_config_entries_incref(b->entries);
77
+ *out = b->entries;
92
78
 
93
- git_mutex_unlock(&h->values_mutex);
79
+ git_mutex_unlock(&b->values_mutex);
94
80
 
95
- return entries;
81
+ return 0;
96
82
  }
97
83
 
98
- static void config_file_clear(struct config_file *file)
84
+ static void config_file_clear(config_file *file)
99
85
  {
100
- struct config_file *include;
86
+ config_file *include;
101
87
  uint32_t i;
102
88
 
103
89
  if (file == NULL)
@@ -111,31 +97,40 @@ static void config_file_clear(struct config_file *file)
111
97
  git__free(file->path);
112
98
  }
113
99
 
114
- static int config_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
100
+ static int config_file_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
115
101
  {
102
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
116
103
  int res;
117
- diskfile_backend *b = (diskfile_backend *)cfg;
118
104
 
119
- b->header.level = level;
120
- b->header.repo = repo;
105
+ b->level = level;
106
+ b->repo = repo;
121
107
 
122
- if ((res = git_config_entries_new(&b->header.entries)) < 0)
108
+ if ((res = git_config_entries_new(&b->entries)) < 0)
123
109
  return res;
124
110
 
125
111
  if (!git_path_exists(b->file.path))
126
112
  return 0;
127
113
 
128
- if (res < 0 || (res = config_read(b->header.entries, repo, &b->file, level, 0)) < 0) {
129
- git_config_entries_free(b->header.entries);
130
- b->header.entries = NULL;
114
+ /*
115
+ * git silently ignores configuration files that are not
116
+ * readable. We emulate that behavior. This is particularly
117
+ * important for sandboxed applications on macOS where the
118
+ * git configuration files may not be readable.
119
+ */
120
+ if (p_access(b->file.path, R_OK) < 0)
121
+ return GIT_ENOTFOUND;
122
+
123
+ if (res < 0 || (res = config_file_read(b->entries, repo, &b->file, level, 0)) < 0) {
124
+ git_config_entries_free(b->entries);
125
+ b->entries = NULL;
131
126
  }
132
127
 
133
128
  return res;
134
129
  }
135
130
 
136
- static int config_is_modified(int *modified, struct config_file *file)
131
+ static int config_file_is_modified(int *modified, config_file *file)
137
132
  {
138
- git_config_file *include;
133
+ config_file *include;
139
134
  git_buf buf = GIT_BUF_INIT;
140
135
  git_oid hash;
141
136
  uint32_t i;
@@ -143,6 +138,9 @@ static int config_is_modified(int *modified, struct config_file *file)
143
138
 
144
139
  *modified = 0;
145
140
 
141
+ if (!git_futils_filestamp_check(&file->stamp, file->path))
142
+ goto check_includes;
143
+
146
144
  if ((error = git_futils_readbuffer(&buf, file->path)) < 0)
147
145
  goto out;
148
146
 
@@ -154,8 +152,9 @@ static int config_is_modified(int *modified, struct config_file *file)
154
152
  goto out;
155
153
  }
156
154
 
155
+ check_includes:
157
156
  git_array_foreach(file->includes, i, include) {
158
- if ((error = config_is_modified(modified, include)) < 0 || *modified)
157
+ if ((error = config_file_is_modified(modified, include)) < 0 || *modified)
159
158
  goto out;
160
159
  }
161
160
 
@@ -165,89 +164,125 @@ out:
165
164
  return error;
166
165
  }
167
166
 
168
- static int config_refresh(git_config_backend *cfg)
167
+ static int config_file_set_entries(git_config_backend *cfg, git_config_entries *entries)
169
168
  {
170
- diskfile_backend *b = (diskfile_backend *)cfg;
171
- git_config_entries *entries = NULL, *tmp;
172
- git_config_file *include;
173
- int error, modified;
169
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
170
+ git_config_entries *old = NULL;
171
+ config_file *include;
172
+ int error;
174
173
  uint32_t i;
175
174
 
176
- if (b->header.parent.readonly)
177
- return config_error_readonly();
175
+ if (b->parent.readonly) {
176
+ git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
177
+ return -1;
178
+ }
178
179
 
179
- error = config_is_modified(&modified, &b->file);
180
- if (error < 0 && error != GIT_ENOTFOUND)
180
+ git_array_foreach(b->file.includes, i, include)
181
+ config_file_clear(include);
182
+ git_array_clear(b->file.includes);
183
+
184
+ if ((error = git_mutex_lock(&b->values_mutex)) < 0) {
185
+ git_error_set(GIT_ERROR_OS, "failed to lock config backend");
181
186
  goto out;
187
+ }
182
188
 
183
- if (!modified)
184
- return 0;
189
+ old = b->entries;
190
+ b->entries = entries;
185
191
 
186
- if ((error = git_config_entries_new(&entries)) < 0)
187
- goto out;
192
+ git_mutex_unlock(&b->values_mutex);
188
193
 
189
- /* Reparse the current configuration */
190
- git_array_foreach(b->file.includes, i, include) {
191
- config_file_clear(include);
192
- }
193
- git_array_clear(b->file.includes);
194
+ out:
195
+ git_config_entries_free(old);
196
+ return error;
197
+ }
198
+
199
+ static int config_file_refresh_from_buffer(git_config_backend *cfg, const char *buf, size_t buflen)
200
+ {
201
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
202
+ git_config_entries *entries = NULL;
203
+ int error;
194
204
 
195
- if ((error = config_read(entries, b->header.repo, &b->file, b->header.level, 0)) < 0)
205
+ if ((error = git_config_entries_new(&entries)) < 0 ||
206
+ (error = config_file_read_buffer(entries, b->repo, &b->file,
207
+ b->level, 0, buf, buflen)) < 0 ||
208
+ (error = config_file_set_entries(cfg, entries)) < 0)
196
209
  goto out;
197
210
 
198
- if ((error = git_mutex_lock(&b->header.values_mutex)) < 0) {
199
- git_error_set(GIT_ERROR_OS, "failed to lock config backend");
211
+ entries = NULL;
212
+ out:
213
+ git_config_entries_free(entries);
214
+ return error;
215
+ }
216
+
217
+ static int config_file_refresh(git_config_backend *cfg)
218
+ {
219
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
220
+ git_config_entries *entries = NULL;
221
+ int error, modified;
222
+
223
+ if (cfg->readonly)
224
+ return 0;
225
+
226
+ if ((error = config_file_is_modified(&modified, &b->file)) < 0 && error != GIT_ENOTFOUND)
200
227
  goto out;
201
- }
202
228
 
203
- tmp = b->header.entries;
204
- b->header.entries = entries;
205
- entries = tmp;
229
+ if (!modified)
230
+ return 0;
206
231
 
207
- git_mutex_unlock(&b->header.values_mutex);
232
+ if ((error = git_config_entries_new(&entries)) < 0 ||
233
+ (error = config_file_read(entries, b->repo, &b->file, b->level, 0)) < 0 ||
234
+ (error = config_file_set_entries(cfg, entries)) < 0)
235
+ goto out;
208
236
 
237
+ entries = NULL;
209
238
  out:
210
239
  git_config_entries_free(entries);
211
240
 
212
241
  return (error == GIT_ENOTFOUND) ? 0 : error;
213
242
  }
214
243
 
215
- static void backend_free(git_config_backend *_backend)
244
+ static void config_file_free(git_config_backend *_backend)
216
245
  {
217
- diskfile_backend *backend = (diskfile_backend *)_backend;
246
+ config_file_backend *backend = GIT_CONTAINER_OF(_backend, config_file_backend, parent);
218
247
 
219
248
  if (backend == NULL)
220
249
  return;
221
250
 
222
251
  config_file_clear(&backend->file);
223
- git_config_entries_free(backend->header.entries);
224
- git_mutex_free(&backend->header.values_mutex);
252
+ git_config_entries_free(backend->entries);
253
+ git_mutex_free(&backend->values_mutex);
225
254
  git__free(backend);
226
255
  }
227
256
 
228
- static int config_iterator_new(
257
+ static int config_file_iterator(
229
258
  git_config_iterator **iter,
230
- struct git_config_backend* backend)
259
+ struct git_config_backend *backend)
231
260
  {
232
- diskfile_header *bh = (diskfile_header *) backend;
233
- git_config_entries *entries;
261
+ config_file_backend *b = GIT_CONTAINER_OF(backend, config_file_backend, parent);
262
+ git_config_entries *dupped = NULL, *entries = NULL;
234
263
  int error;
235
264
 
236
- if ((error = git_config_entries_dup(&entries, bh->entries)) < 0)
237
- return error;
238
-
239
- if ((error = git_config_entries_iterator_new(iter, entries)) < 0)
265
+ if ((error = config_file_refresh(backend)) < 0 ||
266
+ (error = config_file_entries_take(&entries, b)) < 0 ||
267
+ (error = git_config_entries_dup(&dupped, entries)) < 0 ||
268
+ (error = git_config_entries_iterator_new(iter, dupped)) < 0)
240
269
  goto out;
241
270
 
242
271
  out:
243
272
  /* Let iterator delete duplicated entries when it's done */
244
273
  git_config_entries_free(entries);
274
+ git_config_entries_free(dupped);
245
275
  return error;
246
276
  }
247
277
 
248
- static int config_set(git_config_backend *cfg, const char *name, const char *value)
278
+ static int config_file_snapshot(git_config_backend **out, git_config_backend *backend)
249
279
  {
250
- diskfile_backend *b = (diskfile_backend *)cfg;
280
+ return git_config_backend_snapshot(out, backend);
281
+ }
282
+
283
+ static int config_file_set(git_config_backend *cfg, const char *name, const char *value)
284
+ {
285
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
251
286
  git_config_entries *entries;
252
287
  git_config_entry *existing;
253
288
  char *key, *esc_value = NULL;
@@ -256,8 +291,8 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
256
291
  if ((error = git_config__normalize_name(name, &key)) < 0)
257
292
  return error;
258
293
 
259
- if ((entries = diskfile_entries_take(&b->header)) == NULL)
260
- return -1;
294
+ if ((error = config_file_entries_take(&entries, b)) < 0)
295
+ return error;
261
296
 
262
297
  /* Check whether we'd be modifying an included or multivar key */
263
298
  if ((error = git_config_entries_get_unique(&existing, entries, key)) < 0) {
@@ -277,11 +312,9 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val
277
312
  GIT_ERROR_CHECK_ALLOC(esc_value);
278
313
  }
279
314
 
280
- if ((error = config_write(b, name, key, NULL, esc_value)) < 0)
315
+ if ((error = config_file_write(b, name, key, NULL, esc_value)) < 0)
281
316
  goto out;
282
317
 
283
- error = config_refresh(cfg);
284
-
285
318
  out:
286
319
  git_config_entries_free(entries);
287
320
  git__free(esc_value);
@@ -290,7 +323,7 @@ out:
290
323
  }
291
324
 
292
325
  /* release the map containing the entry as an equivalent to freeing it */
293
- static void free_diskfile_entry(git_config_entry *entry)
326
+ static void config_file_entry_free(git_config_entry *entry)
294
327
  {
295
328
  git_config_entries *entries = (git_config_entries *) entry->payload;
296
329
  git_config_entries_free(entries);
@@ -299,67 +332,61 @@ static void free_diskfile_entry(git_config_entry *entry)
299
332
  /*
300
333
  * Internal function that actually gets the value in string form
301
334
  */
302
- static int config_get(git_config_backend *cfg, const char *key, git_config_entry **out)
335
+ static int config_file_get(git_config_backend *cfg, const char *key, git_config_entry **out)
303
336
  {
304
- diskfile_header *h = (diskfile_header *)cfg;
337
+ config_file_backend *h = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
305
338
  git_config_entries *entries = NULL;
306
339
  git_config_entry *entry;
307
340
  int error = 0;
308
341
 
309
- if (!h->parent.readonly && ((error = config_refresh(cfg)) < 0))
342
+ if (!h->parent.readonly && ((error = config_file_refresh(cfg)) < 0))
310
343
  return error;
311
344
 
312
- if ((entries = diskfile_entries_take(h)) == NULL)
313
- return -1;
345
+ if ((error = config_file_entries_take(&entries, h)) < 0)
346
+ return error;
314
347
 
315
348
  if ((error = (git_config_entries_get(&entry, entries, key))) < 0) {
316
349
  git_config_entries_free(entries);
317
350
  return error;
318
351
  }
319
352
 
320
- entry->free = free_diskfile_entry;
353
+ entry->free = config_file_entry_free;
321
354
  entry->payload = entries;
322
355
  *out = entry;
323
356
 
324
357
  return 0;
325
358
  }
326
359
 
327
- static int config_set_multivar(
360
+ static int config_file_set_multivar(
328
361
  git_config_backend *cfg, const char *name, const char *regexp, const char *value)
329
362
  {
330
- diskfile_backend *b = (diskfile_backend *)cfg;
331
- char *key;
332
- regex_t preg;
363
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
364
+ git_regexp preg;
333
365
  int result;
366
+ char *key;
334
367
 
335
368
  assert(regexp);
336
369
 
337
370
  if ((result = git_config__normalize_name(name, &key)) < 0)
338
371
  return result;
339
372
 
340
- result = p_regcomp(&preg, regexp, REG_EXTENDED);
341
- if (result != 0) {
342
- git_error_set_regex(&preg, result);
343
- result = -1;
373
+ if ((result = git_regexp_compile(&preg, regexp, 0)) < 0)
344
374
  goto out;
345
- }
346
375
 
347
- /* If we do have it, set call config_write() and reload */
348
- if ((result = config_write(b, name, key, &preg, value)) < 0)
376
+ /* If we do have it, set call config_file_write() and reload */
377
+ if ((result = config_file_write(b, name, key, &preg, value)) < 0)
349
378
  goto out;
350
379
 
351
- result = config_refresh(cfg);
352
-
353
380
  out:
354
381
  git__free(key);
355
- regfree(&preg);
382
+ git_regexp_dispose(&preg);
356
383
 
357
384
  return result;
358
385
  }
359
386
 
360
- static int config_delete(git_config_backend *cfg, const char *name)
387
+ static int config_file_delete(git_config_backend *cfg, const char *name)
361
388
  {
362
- diskfile_backend *b = (diskfile_backend *)cfg;
389
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
363
390
  git_config_entries *entries = NULL;
364
391
  git_config_entry *entry;
365
392
  char *key = NULL;
@@ -368,7 +395,7 @@ static int config_delete(git_config_backend *cfg, const char *name)
368
395
  if ((error = git_config__normalize_name(name, &key)) < 0)
369
396
  goto out;
370
397
 
371
- if ((entries = diskfile_entries_take(&b->header)) == NULL)
398
+ if ((error = config_file_entries_take(&entries, b)) < 0)
372
399
  goto out;
373
400
 
374
401
  /* Check whether we'd be modifying an included or multivar key */
@@ -378,10 +405,7 @@ static int config_delete(git_config_backend *cfg, const char *name)
378
405
  goto out;
379
406
  }
380
407
 
381
- if ((error = config_write(b, name, entry->name, NULL, NULL)) < 0)
382
- goto out;
383
-
384
- if ((error = config_refresh(cfg)) < 0)
408
+ if ((error = config_file_write(b, name, entry->name, NULL, NULL)) < 0)
385
409
  goto out;
386
410
 
387
411
  out:
@@ -390,22 +414,20 @@ out:
390
414
  return error;
391
415
  }
392
416
 
393
- static int config_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp)
417
+ static int config_file_delete_multivar(git_config_backend *cfg, const char *name, const char *regexp)
394
418
  {
395
- diskfile_backend *b = (diskfile_backend *)cfg;
419
+ config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
396
420
  git_config_entries *entries = NULL;
397
421
  git_config_entry *entry = NULL;
398
- regex_t preg = { 0 };
422
+ git_regexp preg = GIT_REGEX_INIT;
399
423
  char *key = NULL;
400
424
  int result;
401
425
 
402
426
  if ((result = git_config__normalize_name(name, &key)) < 0)
403
427
  goto out;
404
428
 
405
- if ((entries = diskfile_entries_take(&b->header)) == NULL) {
406
- result = -1;
429
+ if ((result = config_file_entries_take(&entries, b)) < 0)
407
430
  goto out;
408
- }
409
431
 
410
432
  if ((result = git_config_entries_get(&entry, entries, key)) < 0) {
411
433
  if (result == GIT_ENOTFOUND)
@@ -413,28 +435,22 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con
413
435
  goto out;
414
436
  }
415
437
 
416
- if ((result = p_regcomp(&preg, regexp, REG_EXTENDED)) != 0) {
417
- git_error_set_regex(&preg, result);
418
- result = -1;
438
+ if ((result = git_regexp_compile(&preg, regexp, 0)) < 0)
419
439
  goto out;
420
- }
421
440
 
422
- if ((result = config_write(b, name, key, &preg, NULL)) < 0)
423
- goto out;
424
-
425
- if ((result = config_refresh(cfg)) < 0)
441
+ if ((result = config_file_write(b, name, key, &preg, NULL)) < 0)
426
442
  goto out;
427
443
 
428
444
  out:
429
445
  git_config_entries_free(entries);
430
446
  git__free(key);
431
- regfree(&preg);
447
+ git_regexp_dispose(&preg);
432
448
  return result;
433
449
  }
434
450
 
435
- static int config_lock(git_config_backend *_cfg)
451
+ static int config_file_lock(git_config_backend *_cfg)
436
452
  {
437
- diskfile_backend *cfg = (diskfile_backend *) _cfg;
453
+ config_file_backend *cfg = GIT_CONTAINER_OF(_cfg, config_file_backend, parent);
438
454
  int error;
439
455
 
440
456
  if ((error = git_filebuf_open(&cfg->locked_buf, cfg->file.path, 0, GIT_CONFIG_FILE_MODE)) < 0)
@@ -451,9 +467,9 @@ static int config_lock(git_config_backend *_cfg)
451
467
 
452
468
  }
453
469
 
454
- static int config_unlock(git_config_backend *_cfg, int success)
470
+ static int config_file_unlock(git_config_backend *_cfg, int success)
455
471
  {
456
- diskfile_backend *cfg = (diskfile_backend *) _cfg;
472
+ config_file_backend *cfg = GIT_CONTAINER_OF(_cfg, config_file_backend, parent);
457
473
  int error = 0;
458
474
 
459
475
  if (success) {
@@ -470,145 +486,29 @@ static int config_unlock(git_config_backend *_cfg, int success)
470
486
 
471
487
  int git_config_backend_from_file(git_config_backend **out, const char *path)
472
488
  {
473
- diskfile_backend *backend;
489
+ config_file_backend *backend;
474
490
 
475
- backend = git__calloc(1, sizeof(diskfile_backend));
491
+ backend = git__calloc(1, sizeof(config_file_backend));
476
492
  GIT_ERROR_CHECK_ALLOC(backend);
477
493
 
478
- backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION;
479
- git_mutex_init(&backend->header.values_mutex);
494
+ backend->parent.version = GIT_CONFIG_BACKEND_VERSION;
495
+ git_mutex_init(&backend->values_mutex);
480
496
 
481
497
  backend->file.path = git__strdup(path);
482
498
  GIT_ERROR_CHECK_ALLOC(backend->file.path);
483
499
  git_array_init(backend->file.includes);
484
500
 
485
- backend->header.parent.open = config_open;
486
- backend->header.parent.get = config_get;
487
- backend->header.parent.set = config_set;
488
- backend->header.parent.set_multivar = config_set_multivar;
489
- backend->header.parent.del = config_delete;
490
- backend->header.parent.del_multivar = config_delete_multivar;
491
- backend->header.parent.iterator = config_iterator_new;
492
- backend->header.parent.snapshot = config_snapshot;
493
- backend->header.parent.lock = config_lock;
494
- backend->header.parent.unlock = config_unlock;
495
- backend->header.parent.free = backend_free;
496
-
497
- *out = (git_config_backend *)backend;
498
-
499
- return 0;
500
- }
501
-
502
- static int config_set_readonly(git_config_backend *cfg, const char *name, const char *value)
503
- {
504
- GIT_UNUSED(cfg);
505
- GIT_UNUSED(name);
506
- GIT_UNUSED(value);
507
-
508
- return config_error_readonly();
509
- }
510
-
511
- static int config_set_multivar_readonly(
512
- git_config_backend *cfg, const char *name, const char *regexp, const char *value)
513
- {
514
- GIT_UNUSED(cfg);
515
- GIT_UNUSED(name);
516
- GIT_UNUSED(regexp);
517
- GIT_UNUSED(value);
518
-
519
- return config_error_readonly();
520
- }
521
-
522
- static int config_delete_multivar_readonly(git_config_backend *cfg, const char *name, const char *regexp)
523
- {
524
- GIT_UNUSED(cfg);
525
- GIT_UNUSED(name);
526
- GIT_UNUSED(regexp);
527
-
528
- return config_error_readonly();
529
- }
530
-
531
- static int config_delete_readonly(git_config_backend *cfg, const char *name)
532
- {
533
- GIT_UNUSED(cfg);
534
- GIT_UNUSED(name);
535
-
536
- return config_error_readonly();
537
- }
538
-
539
- static int config_lock_readonly(git_config_backend *_cfg)
540
- {
541
- GIT_UNUSED(_cfg);
542
-
543
- return config_error_readonly();
544
- }
545
-
546
- static int config_unlock_readonly(git_config_backend *_cfg, int success)
547
- {
548
- GIT_UNUSED(_cfg);
549
- GIT_UNUSED(success);
550
-
551
- return config_error_readonly();
552
- }
553
-
554
- static void backend_readonly_free(git_config_backend *_backend)
555
- {
556
- diskfile_backend *backend = (diskfile_backend *)_backend;
557
-
558
- if (backend == NULL)
559
- return;
560
-
561
- git_config_entries_free(backend->header.entries);
562
- git_mutex_free(&backend->header.values_mutex);
563
- git__free(backend);
564
- }
565
-
566
- static int config_readonly_open(git_config_backend *cfg, git_config_level_t level, const git_repository *repo)
567
- {
568
- diskfile_readonly_backend *b = (diskfile_readonly_backend *) cfg;
569
- diskfile_backend *src = b->snapshot_from;
570
- diskfile_header *src_header = &src->header;
571
- git_config_entries *entries;
572
- int error;
573
-
574
- if (!src_header->parent.readonly && (error = config_refresh(&src_header->parent)) < 0)
575
- return error;
576
-
577
- /* We're just copying data, don't care about the level or repo*/
578
- GIT_UNUSED(level);
579
- GIT_UNUSED(repo);
580
-
581
- if ((entries = diskfile_entries_take(src_header)) == NULL)
582
- return -1;
583
- b->header.entries = entries;
584
-
585
- return 0;
586
- }
587
-
588
- static int config_snapshot(git_config_backend **out, git_config_backend *in)
589
- {
590
- diskfile_readonly_backend *backend;
591
-
592
- backend = git__calloc(1, sizeof(diskfile_readonly_backend));
593
- GIT_ERROR_CHECK_ALLOC(backend);
594
-
595
- backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION;
596
- git_mutex_init(&backend->header.values_mutex);
597
-
598
- backend->snapshot_from = (diskfile_backend *) in;
599
-
600
- backend->header.parent.readonly = 1;
601
- backend->header.parent.version = GIT_CONFIG_BACKEND_VERSION;
602
- backend->header.parent.open = config_readonly_open;
603
- backend->header.parent.get = config_get;
604
- backend->header.parent.set = config_set_readonly;
605
- backend->header.parent.set_multivar = config_set_multivar_readonly;
606
- backend->header.parent.del = config_delete_readonly;
607
- backend->header.parent.del_multivar = config_delete_multivar_readonly;
608
- backend->header.parent.iterator = config_iterator_new;
609
- backend->header.parent.lock = config_lock_readonly;
610
- backend->header.parent.unlock = config_unlock_readonly;
611
- backend->header.parent.free = backend_readonly_free;
501
+ backend->parent.open = config_file_open;
502
+ backend->parent.get = config_file_get;
503
+ backend->parent.set = config_file_set;
504
+ backend->parent.set_multivar = config_file_set_multivar;
505
+ backend->parent.del = config_file_delete;
506
+ backend->parent.del_multivar = config_file_delete_multivar;
507
+ backend->parent.iterator = config_file_iterator;
508
+ backend->parent.snapshot = config_file_snapshot;
509
+ backend->parent.lock = config_file_lock;
510
+ backend->parent.unlock = config_file_unlock;
511
+ backend->parent.free = config_file_free;
612
512
 
613
513
  *out = (git_config_backend *)backend;
614
514
 
@@ -656,10 +556,9 @@ static char *escape_value(const char *ptr)
656
556
  return git_buf_detach(&buf);
657
557
  }
658
558
 
659
- static int parse_include(git_config_parser *reader,
660
- diskfile_parse_state *parse_data, const char *file)
559
+ static int parse_include(config_file_parse_data *parse_data, const char *file)
661
560
  {
662
- struct config_file *include;
561
+ config_file *include;
663
562
  git_buf path = GIT_BUF_INIT;
664
563
  char *dir;
665
564
  int result;
@@ -667,7 +566,7 @@ static int parse_include(git_config_parser *reader,
667
566
  if (!file)
668
567
  return 0;
669
568
 
670
- if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
569
+ if ((result = git_path_dirname_r(&path, parse_data->file->path)) < 0)
671
570
  return result;
672
571
 
673
572
  dir = git_buf_detach(&path);
@@ -677,14 +576,14 @@ static int parse_include(git_config_parser *reader,
677
576
  if (result < 0)
678
577
  return result;
679
578
 
680
- include = git_array_alloc(reader->file->includes);
579
+ include = git_array_alloc(parse_data->file->includes);
681
580
  GIT_ERROR_CHECK_ALLOC(include);
682
581
  memset(include, 0, sizeof(*include));
683
582
  git_array_init(include->includes);
684
583
  include->path = git_buf_detach(&path);
685
584
 
686
- result = config_read(parse_data->entries, parse_data->repo,
687
- include, parse_data->level, parse_data->depth+1);
585
+ result = config_file_read(parse_data->entries, parse_data->repo, include,
586
+ parse_data->level, parse_data->depth+1);
688
587
 
689
588
  if (result == GIT_ENOTFOUND) {
690
589
  git_error_clear();
@@ -698,41 +597,41 @@ static int do_match_gitdir(
698
597
  int *matches,
699
598
  const git_repository *repo,
700
599
  const char *cfg_file,
701
- const char *value,
600
+ const char *condition,
702
601
  bool case_insensitive)
703
602
  {
704
- git_buf path = GIT_BUF_INIT;
705
- int error, fnmatch_flags;
706
-
707
- if (value[0] == '.' && git_path_is_dirsep(value[1])) {
708
- git_path_dirname_r(&path, cfg_file);
709
- git_buf_joinpath(&path, path.ptr, value + 2);
710
- } else if (value[0] == '~' && git_path_is_dirsep(value[1]))
711
- git_sysdir_expand_global_file(&path, value + 1);
712
- else if (!git_path_is_absolute(value))
713
- git_buf_joinpath(&path, "**", value);
603
+ git_buf pattern = GIT_BUF_INIT, gitdir = GIT_BUF_INIT;
604
+ int error;
605
+
606
+ if (condition[0] == '.' && git_path_is_dirsep(condition[1])) {
607
+ git_path_dirname_r(&pattern, cfg_file);
608
+ git_buf_joinpath(&pattern, pattern.ptr, condition + 2);
609
+ } else if (condition[0] == '~' && git_path_is_dirsep(condition[1]))
610
+ git_sysdir_expand_global_file(&pattern, condition + 1);
611
+ else if (!git_path_is_absolute(condition))
612
+ git_buf_joinpath(&pattern, "**", condition);
714
613
  else
715
- git_buf_sets(&path, value);
614
+ git_buf_sets(&pattern, condition);
615
+
616
+ if (git_path_is_dirsep(condition[strlen(condition) - 1]))
617
+ git_buf_puts(&pattern, "**");
716
618
 
717
- if (git_buf_oom(&path)) {
619
+ if (git_buf_oom(&pattern)) {
718
620
  error = -1;
719
621
  goto out;
720
622
  }
721
623
 
722
- if (git_path_is_dirsep(value[strlen(value) - 1]))
723
- git_buf_puts(&path, "**");
724
-
725
- fnmatch_flags = FNM_PATHNAME|FNM_LEADING_DIR;
726
- if (case_insensitive)
727
- fnmatch_flags |= FNM_IGNORECASE;
728
-
729
- if ((error = p_fnmatch(path.ptr, git_repository_path(repo), fnmatch_flags)) < 0)
624
+ if ((error = git_repository_item_path(&gitdir, repo, GIT_REPOSITORY_ITEM_GITDIR)) < 0)
730
625
  goto out;
731
626
 
732
- *matches = (error == 0);
627
+ if (git_path_is_dirsep(gitdir.ptr[gitdir.size - 1]))
628
+ git_buf_truncate(&gitdir, gitdir.size - 1);
733
629
 
630
+ *matches = wildmatch(pattern.ptr, gitdir.ptr,
631
+ WM_PATHNAME | (case_insensitive ? WM_CASEFOLD : 0)) == WM_MATCH;
734
632
  out:
735
- git_buf_dispose(&path);
633
+ git_buf_dispose(&pattern);
634
+ git_buf_dispose(&gitdir);
736
635
  return error;
737
636
  }
738
637
 
@@ -754,16 +653,67 @@ static int conditional_match_gitdir_i(
754
653
  return do_match_gitdir(matches, repo, cfg_file, value, true);
755
654
  }
756
655
 
656
+ static int conditional_match_onbranch(
657
+ int *matches,
658
+ const git_repository *repo,
659
+ const char *cfg_file,
660
+ const char *condition)
661
+ {
662
+ git_buf reference = GIT_BUF_INIT, buf = GIT_BUF_INIT;
663
+ int error;
664
+
665
+ GIT_UNUSED(cfg_file);
666
+
667
+ /*
668
+ * NOTE: you cannot use `git_repository_head` here. Looking up the
669
+ * HEAD reference will create the ODB, which causes us to read the
670
+ * repo's config for keys like core.precomposeUnicode. As we're
671
+ * just parsing the config right now, though, this would result in
672
+ * an endless recursion.
673
+ */
674
+
675
+ if ((error = git_buf_joinpath(&buf, git_repository_path(repo), GIT_HEAD_FILE)) < 0 ||
676
+ (error = git_futils_readbuffer(&reference, buf.ptr)) < 0)
677
+ goto out;
678
+ git_buf_rtrim(&reference);
679
+
680
+ if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)))
681
+ goto out;
682
+ git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF));
683
+
684
+ if (git__strncmp(reference.ptr, GIT_REFS_HEADS_DIR, strlen(GIT_REFS_HEADS_DIR)))
685
+ goto out;
686
+ git_buf_consume(&reference, reference.ptr + strlen(GIT_REFS_HEADS_DIR));
687
+
688
+ /*
689
+ * If the condition ends with a '/', then we should treat it as if
690
+ * it had '**' appended.
691
+ */
692
+ if ((error = git_buf_sets(&buf, condition)) < 0)
693
+ goto out;
694
+ if (git_path_is_dirsep(condition[strlen(condition) - 1]) &&
695
+ (error = git_buf_puts(&buf, "**")) < 0)
696
+ goto out;
697
+
698
+ *matches = wildmatch(buf.ptr, reference.ptr, WM_PATHNAME) == WM_MATCH;
699
+ out:
700
+ git_buf_dispose(&reference);
701
+ git_buf_dispose(&buf);
702
+
703
+ return error;
704
+
705
+ }
706
+
757
707
  static const struct {
758
708
  const char *prefix;
759
709
  int (*matches)(int *matches, const git_repository *repo, const char *cfg, const char *value);
760
710
  } conditions[] = {
761
711
  { "gitdir:", conditional_match_gitdir },
762
- { "gitdir/i:", conditional_match_gitdir_i }
712
+ { "gitdir/i:", conditional_match_gitdir_i },
713
+ { "onbranch:", conditional_match_onbranch }
763
714
  };
764
715
 
765
- static int parse_conditional_include(git_config_parser *reader,
766
- diskfile_parse_state *parse_data, const char *section, const char *file)
716
+ static int parse_conditional_include(config_file_parse_data *parse_data, const char *section, const char *file)
767
717
  {
768
718
  char *condition;
769
719
  size_t i;
@@ -781,12 +731,12 @@ static int parse_conditional_include(git_config_parser *reader,
781
731
 
782
732
  if ((error = conditions[i].matches(&matches,
783
733
  parse_data->repo,
784
- parse_data->file_path,
734
+ parse_data->file->path,
785
735
  condition + strlen(conditions[i].prefix))) < 0)
786
736
  break;
787
737
 
788
738
  if (matches)
789
- error = parse_include(reader, parse_data, file);
739
+ error = parse_include(parse_data, file);
790
740
 
791
741
  break;
792
742
  }
@@ -804,12 +754,13 @@ static int read_on_variable(
804
754
  size_t line_len,
805
755
  void *data)
806
756
  {
807
- diskfile_parse_state *parse_data = (diskfile_parse_state *)data;
757
+ config_file_parse_data *parse_data = (config_file_parse_data *)data;
808
758
  git_buf buf = GIT_BUF_INIT;
809
759
  git_config_entry *entry;
810
760
  const char *c;
811
761
  int result = 0;
812
762
 
763
+ GIT_UNUSED(reader);
813
764
  GIT_UNUSED(line);
814
765
  GIT_UNUSED(line_len);
815
766
 
@@ -842,25 +793,25 @@ static int read_on_variable(
842
793
 
843
794
  /* Add or append the new config option */
844
795
  if (!git__strcmp(entry->name, "include.path"))
845
- result = parse_include(reader, parse_data, entry->value);
796
+ result = parse_include(parse_data, entry->value);
846
797
  else if (!git__prefixcmp(entry->name, "includeif.") &&
847
798
  !git__suffixcmp(entry->name, ".path"))
848
- result = parse_conditional_include(reader, parse_data,
849
- entry->name, entry->value);
799
+ result = parse_conditional_include(parse_data, entry->name, entry->value);
850
800
 
851
801
  return result;
852
802
  }
853
803
 
854
- static int config_read(
804
+ static int config_file_read_buffer(
855
805
  git_config_entries *entries,
856
806
  const git_repository *repo,
857
- git_config_file *file,
807
+ config_file *file,
858
808
  git_config_level_t level,
859
- int depth)
809
+ int depth,
810
+ const char *buf,
811
+ size_t buflen)
860
812
  {
861
- diskfile_parse_state parse_data;
813
+ config_file_parse_data parse_data;
862
814
  git_config_parser reader;
863
- git_buf contents = GIT_BUF_INIT;
864
815
  int error;
865
816
 
866
817
  if (depth >= MAX_INCLUDE_DEPTH) {
@@ -868,30 +819,55 @@ static int config_read(
868
819
  return -1;
869
820
  }
870
821
 
871
- if ((error = git_futils_readbuffer(&contents, file->path)) < 0)
872
- goto out;
873
-
874
- git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size);
875
-
876
- if ((error = git_hash_buf(&file->checksum, contents.ptr, contents.size)) < 0)
877
- goto out;
878
-
879
822
  /* Initialize the reading position */
880
- reader.file = file;
881
- git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size);
823
+ reader.path = file->path;
824
+ git_parse_ctx_init(&reader.ctx, buf, buflen);
882
825
 
883
826
  /* If the file is empty, there's nothing for us to do */
884
- if (!reader.ctx.content || *reader.ctx.content == '\0')
827
+ if (!reader.ctx.content || *reader.ctx.content == '\0') {
828
+ error = 0;
885
829
  goto out;
830
+ }
886
831
 
887
832
  parse_data.repo = repo;
888
- parse_data.file_path = file->path;
833
+ parse_data.file = file;
889
834
  parse_data.entries = entries;
890
835
  parse_data.level = level;
891
836
  parse_data.depth = depth;
892
837
 
893
838
  error = git_config_parse(&reader, NULL, read_on_variable, NULL, NULL, &parse_data);
894
839
 
840
+ out:
841
+ return error;
842
+ }
843
+
844
+ static int config_file_read(
845
+ git_config_entries *entries,
846
+ const git_repository *repo,
847
+ config_file *file,
848
+ git_config_level_t level,
849
+ int depth)
850
+ {
851
+ git_buf contents = GIT_BUF_INIT;
852
+ struct stat st;
853
+ int error;
854
+
855
+ if (p_stat(file->path, &st) < 0) {
856
+ error = git_path_set_error(errno, file->path, "stat");
857
+ goto out;
858
+ }
859
+
860
+ if ((error = git_futils_readbuffer(&contents, file->path)) < 0)
861
+ goto out;
862
+
863
+ git_futils_filestamp_set_from_stat(&file->stamp, &st);
864
+ if ((error = git_hash_buf(&file->checksum, contents.ptr, contents.size)) < 0)
865
+ goto out;
866
+
867
+ if ((error = config_file_read_buffer(entries, repo, file, level, depth,
868
+ contents.ptr, contents.size)) < 0)
869
+ goto out;
870
+
895
871
  out:
896
872
  git_buf_dispose(&contents);
897
873
  return error;
@@ -954,7 +930,7 @@ struct write_data {
954
930
  const char *section;
955
931
  const char *orig_name;
956
932
  const char *name;
957
- const regex_t *preg;
933
+ const git_regexp *preg;
958
934
  const char *value;
959
935
  };
960
936
 
@@ -1059,7 +1035,7 @@ static int write_on_variable(
1059
1035
 
1060
1036
  /* If we have a regex to match the value, see if it matches */
1061
1037
  if (has_matched && write_data->preg != NULL)
1062
- has_matched = (regexec(write_data->preg, var_value, 0, NULL, 0) == 0);
1038
+ has_matched = (git_regexp_match(write_data->preg, var_value) == 0);
1063
1039
 
1064
1040
  /* If this isn't the name/value we're looking for, simply dump the
1065
1041
  * existing data back out and continue on.
@@ -1120,39 +1096,33 @@ static int write_on_eof(
1120
1096
  /*
1121
1097
  * This is pretty much the parsing, except we write out anything we don't have
1122
1098
  */
1123
- static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char* value)
1099
+ static int config_file_write(config_file_backend *cfg, const char *orig_key, const char *key, const git_regexp *preg, const char* value)
1100
+
1124
1101
  {
1125
- int result;
1126
- char *orig_section, *section, *orig_name, *name, *ldot;
1127
- git_filebuf file = GIT_FILEBUF_INIT;
1102
+ char *orig_section = NULL, *section = NULL, *orig_name, *name, *ldot;
1128
1103
  git_buf buf = GIT_BUF_INIT, contents = GIT_BUF_INIT;
1129
- git_config_parser reader;
1104
+ git_config_parser parser = GIT_CONFIG_PARSER_INIT;
1105
+ git_filebuf file = GIT_FILEBUF_INIT;
1130
1106
  struct write_data write_data;
1107
+ int error;
1131
1108
 
1132
- memset(&reader, 0, sizeof(reader));
1133
- reader.file = &cfg->file;
1109
+ memset(&write_data, 0, sizeof(write_data));
1134
1110
 
1135
1111
  if (cfg->locked) {
1136
- result = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content));
1112
+ error = git_buf_puts(&contents, git_buf_cstr(&cfg->locked_content) == NULL ? "" : git_buf_cstr(&cfg->locked_content));
1137
1113
  } else {
1138
- /* Lock the file */
1139
- if ((result = git_filebuf_open(
1140
- &file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS, GIT_CONFIG_FILE_MODE)) < 0) {
1141
- git_buf_dispose(&contents);
1142
- return result;
1143
- }
1114
+ if ((error = git_filebuf_open(&file, cfg->file.path, GIT_FILEBUF_HASH_CONTENTS,
1115
+ GIT_CONFIG_FILE_MODE)) < 0)
1116
+ goto done;
1144
1117
 
1145
1118
  /* We need to read in our own config file */
1146
- result = git_futils_readbuffer(&contents, cfg->file.path);
1119
+ error = git_futils_readbuffer(&contents, cfg->file.path);
1147
1120
  }
1121
+ if (error < 0 && error != GIT_ENOTFOUND)
1122
+ goto done;
1148
1123
 
1149
- /* Initialise the reading position */
1150
- if (result == 0 || result == GIT_ENOTFOUND) {
1151
- git_parse_ctx_init(&reader.ctx, contents.ptr, contents.size);
1152
- } else {
1153
- git_filebuf_cleanup(&file);
1154
- return -1; /* OS error when reading the file */
1155
- }
1124
+ if ((git_config_parser_init(&parser, cfg->file.path, contents.ptr, contents.size)) < 0)
1125
+ goto done;
1156
1126
 
1157
1127
  ldot = strrchr(key, '.');
1158
1128
  name = ldot + 1;
@@ -1165,30 +1135,16 @@ static int config_write(diskfile_backend *cfg, const char *orig_key, const char
1165
1135
  GIT_ERROR_CHECK_ALLOC(orig_section);
1166
1136
 
1167
1137
  write_data.buf = &buf;
1168
- git_buf_init(&write_data.buffered_comment, 0);
1169
1138
  write_data.orig_section = orig_section;
1170
1139
  write_data.section = section;
1171
- write_data.in_section = 0;
1172
- write_data.preg_replaced = 0;
1173
1140
  write_data.orig_name = orig_name;
1174
1141
  write_data.name = name;
1175
1142
  write_data.preg = preg;
1176
1143
  write_data.value = value;
1177
1144
 
1178
- result = git_config_parse(&reader,
1179
- write_on_section,
1180
- write_on_variable,
1181
- write_on_comment,
1182
- write_on_eof,
1183
- &write_data);
1184
- git__free(section);
1185
- git__free(orig_section);
1186
- git_buf_dispose(&write_data.buffered_comment);
1187
-
1188
- if (result < 0) {
1189
- git_filebuf_cleanup(&file);
1145
+ if ((error = git_config_parse(&parser, write_on_section, write_on_variable,
1146
+ write_on_comment, write_on_eof, &write_data)) < 0)
1190
1147
  goto done;
1191
- }
1192
1148
 
1193
1149
  if (cfg->locked) {
1194
1150
  size_t len = buf.asize;
@@ -1197,12 +1153,22 @@ static int config_write(diskfile_backend *cfg, const char *orig_key, const char
1197
1153
  git_buf_attach(&cfg->locked_content, git_buf_detach(&buf), len);
1198
1154
  } else {
1199
1155
  git_filebuf_write(&file, git_buf_cstr(&buf), git_buf_len(&buf));
1200
- result = git_filebuf_commit(&file);
1156
+
1157
+ if ((error = git_filebuf_commit(&file)) < 0)
1158
+ goto done;
1159
+
1160
+ if ((error = config_file_refresh_from_buffer(&cfg->parent, buf.ptr, buf.size)) < 0)
1161
+ goto done;
1201
1162
  }
1202
1163
 
1203
1164
  done:
1165
+ git__free(section);
1166
+ git__free(orig_section);
1167
+ git_buf_dispose(&write_data.buffered_comment);
1204
1168
  git_buf_dispose(&buf);
1205
1169
  git_buf_dispose(&contents);
1206
- git_parse_ctx_clear(&reader.ctx);
1207
- return result;
1170
+ git_filebuf_cleanup(&file);
1171
+ git_config_parser_dispose(&parser);
1172
+
1173
+ return error;
1208
1174
  }