rugged 0.17.0.b7 → 0.18.0.b1

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 (310) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +88 -32
  3. data/ext/rugged/extconf.rb +4 -2
  4. data/ext/rugged/rugged.c +72 -10
  5. data/ext/rugged/rugged.h +14 -10
  6. data/ext/rugged/rugged_blob.c +8 -10
  7. data/ext/rugged/rugged_branch.c +11 -14
  8. data/ext/rugged/rugged_commit.c +31 -24
  9. data/ext/rugged/rugged_config.c +2 -2
  10. data/ext/rugged/rugged_index.c +133 -198
  11. data/ext/rugged/rugged_note.c +372 -0
  12. data/ext/rugged/rugged_object.c +50 -22
  13. data/ext/rugged/rugged_reference.c +122 -130
  14. data/ext/rugged/rugged_remote.c +72 -29
  15. data/ext/rugged/rugged_repo.c +402 -20
  16. data/ext/rugged/rugged_revwalk.c +7 -3
  17. data/ext/rugged/rugged_settings.c +110 -0
  18. data/ext/rugged/rugged_signature.c +23 -7
  19. data/ext/rugged/rugged_tag.c +32 -16
  20. data/ext/rugged/rugged_tree.c +44 -15
  21. data/lib/rugged.rb +1 -0
  22. data/lib/rugged/index.rb +8 -0
  23. data/lib/rugged/remote.rb +13 -0
  24. data/lib/rugged/repository.rb +3 -3
  25. data/lib/rugged/version.rb +1 -1
  26. data/test/blob_test.rb +13 -15
  27. data/test/branch_test.rb +32 -67
  28. data/test/commit_test.rb +50 -12
  29. data/test/config_test.rb +12 -11
  30. data/test/coverage/HEAD.json +1 -1
  31. data/test/coverage/cover.rb +40 -21
  32. data/test/errors_test.rb +34 -0
  33. data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
  34. data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
  35. data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
  36. data/test/fixtures/testrepo.git/logs/refs/notes/commits +1 -0
  37. data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +1 -0
  38. data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
  39. data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +1 -0
  40. data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
  41. data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
  42. data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +3 -0
  43. data/test/fixtures/testrepo.git/refs/notes/commits +1 -0
  44. data/test/index_test.rb +65 -69
  45. data/test/lib_test.rb +76 -11
  46. data/test/note_test.rb +158 -0
  47. data/test/object_test.rb +8 -11
  48. data/test/reference_test.rb +77 -85
  49. data/test/remote_test.rb +86 -8
  50. data/test/repo_pack_test.rb +9 -7
  51. data/test/repo_reset_test.rb +80 -0
  52. data/test/repo_test.rb +176 -53
  53. data/test/tag_test.rb +44 -7
  54. data/test/test_helper.rb +63 -35
  55. data/test/tree_test.rb +34 -13
  56. data/test/walker_test.rb +14 -14
  57. data/vendor/libgit2/Makefile.embed +1 -1
  58. data/vendor/libgit2/deps/http-parser/http_parser.c +974 -578
  59. data/vendor/libgit2/deps/http-parser/http_parser.h +106 -70
  60. data/vendor/libgit2/deps/regex/regcomp.c +7 -6
  61. data/vendor/libgit2/deps/regex/regex_internal.c +1 -1
  62. data/vendor/libgit2/deps/regex/regex_internal.h +12 -3
  63. data/vendor/libgit2/deps/regex/regexec.c +5 -5
  64. data/vendor/libgit2/include/git2.h +5 -1
  65. data/vendor/libgit2/include/git2/attr.h +4 -2
  66. data/vendor/libgit2/include/git2/blob.h +39 -12
  67. data/vendor/libgit2/include/git2/branch.h +123 -35
  68. data/vendor/libgit2/include/git2/checkout.h +206 -48
  69. data/vendor/libgit2/include/git2/clone.h +72 -27
  70. data/vendor/libgit2/include/git2/commit.h +20 -17
  71. data/vendor/libgit2/include/git2/common.h +67 -1
  72. data/vendor/libgit2/include/git2/config.h +81 -60
  73. data/vendor/libgit2/include/git2/cred_helpers.h +53 -0
  74. data/vendor/libgit2/include/git2/diff.h +459 -150
  75. data/vendor/libgit2/include/git2/errors.h +9 -1
  76. data/vendor/libgit2/include/git2/graph.h +41 -0
  77. data/vendor/libgit2/include/git2/ignore.h +7 -6
  78. data/vendor/libgit2/include/git2/index.h +323 -97
  79. data/vendor/libgit2/include/git2/indexer.h +27 -59
  80. data/vendor/libgit2/include/git2/inttypes.h +4 -0
  81. data/vendor/libgit2/include/git2/merge.h +13 -3
  82. data/vendor/libgit2/include/git2/message.h +14 -8
  83. data/vendor/libgit2/include/git2/net.h +9 -7
  84. data/vendor/libgit2/include/git2/notes.h +88 -29
  85. data/vendor/libgit2/include/git2/object.h +16 -6
  86. data/vendor/libgit2/include/git2/odb.h +80 -17
  87. data/vendor/libgit2/include/git2/odb_backend.h +47 -11
  88. data/vendor/libgit2/include/git2/oid.h +26 -17
  89. data/vendor/libgit2/include/git2/pack.h +62 -8
  90. data/vendor/libgit2/include/git2/push.h +131 -0
  91. data/vendor/libgit2/include/git2/refdb.h +103 -0
  92. data/vendor/libgit2/include/git2/refdb_backend.h +109 -0
  93. data/vendor/libgit2/include/git2/reflog.h +30 -21
  94. data/vendor/libgit2/include/git2/refs.h +215 -193
  95. data/vendor/libgit2/include/git2/refspec.h +22 -2
  96. data/vendor/libgit2/include/git2/remote.h +158 -37
  97. data/vendor/libgit2/include/git2/repository.h +150 -31
  98. data/vendor/libgit2/include/git2/reset.h +43 -9
  99. data/vendor/libgit2/include/git2/revparse.h +48 -4
  100. data/vendor/libgit2/include/git2/revwalk.h +25 -10
  101. data/vendor/libgit2/include/git2/signature.h +20 -12
  102. data/vendor/libgit2/include/git2/stash.h +121 -0
  103. data/vendor/libgit2/include/git2/status.h +122 -53
  104. data/vendor/libgit2/include/git2/strarray.h +17 -11
  105. data/vendor/libgit2/include/git2/submodule.h +42 -7
  106. data/vendor/libgit2/include/git2/tag.h +72 -59
  107. data/vendor/libgit2/include/git2/threads.h +4 -2
  108. data/vendor/libgit2/include/git2/trace.h +68 -0
  109. data/vendor/libgit2/include/git2/transport.h +328 -0
  110. data/vendor/libgit2/include/git2/tree.h +149 -120
  111. data/vendor/libgit2/include/git2/types.h +13 -12
  112. data/vendor/libgit2/include/git2/version.h +3 -3
  113. data/vendor/libgit2/src/amiga/map.c +2 -2
  114. data/vendor/libgit2/src/attr.c +58 -48
  115. data/vendor/libgit2/src/attr.h +4 -18
  116. data/vendor/libgit2/src/attr_file.c +30 -6
  117. data/vendor/libgit2/src/attr_file.h +6 -8
  118. data/vendor/libgit2/src/attrcache.h +24 -0
  119. data/vendor/libgit2/src/blob.c +30 -7
  120. data/vendor/libgit2/src/blob.h +1 -1
  121. data/vendor/libgit2/src/branch.c +361 -68
  122. data/vendor/libgit2/src/branch.h +17 -0
  123. data/vendor/libgit2/src/bswap.h +1 -1
  124. data/vendor/libgit2/src/buf_text.c +291 -0
  125. data/vendor/libgit2/src/buf_text.h +122 -0
  126. data/vendor/libgit2/src/buffer.c +27 -101
  127. data/vendor/libgit2/src/buffer.h +54 -39
  128. data/vendor/libgit2/src/cache.c +15 -6
  129. data/vendor/libgit2/src/cache.h +1 -1
  130. data/vendor/libgit2/src/cc-compat.h +3 -1
  131. data/vendor/libgit2/src/checkout.c +1165 -222
  132. data/vendor/libgit2/src/checkout.h +24 -0
  133. data/vendor/libgit2/src/clone.c +171 -86
  134. data/vendor/libgit2/src/commit.c +44 -45
  135. data/vendor/libgit2/src/commit.h +3 -3
  136. data/vendor/libgit2/src/commit_list.c +194 -0
  137. data/vendor/libgit2/src/commit_list.h +49 -0
  138. data/vendor/libgit2/src/common.h +44 -10
  139. data/vendor/libgit2/src/compress.c +1 -1
  140. data/vendor/libgit2/src/compress.h +1 -1
  141. data/vendor/libgit2/src/config.c +211 -124
  142. data/vendor/libgit2/src/config.h +23 -4
  143. data/vendor/libgit2/src/config_cache.c +2 -2
  144. data/vendor/libgit2/src/config_file.c +129 -53
  145. data/vendor/libgit2/src/config_file.h +10 -8
  146. data/vendor/libgit2/src/crlf.c +66 -67
  147. data/vendor/libgit2/src/date.c +12 -12
  148. data/vendor/libgit2/src/delta-apply.c +14 -1
  149. data/vendor/libgit2/src/delta-apply.h +18 -1
  150. data/vendor/libgit2/src/delta.c +40 -107
  151. data/vendor/libgit2/src/delta.h +19 -17
  152. data/vendor/libgit2/src/diff.c +347 -496
  153. data/vendor/libgit2/src/diff.h +27 -1
  154. data/vendor/libgit2/src/diff_output.c +564 -249
  155. data/vendor/libgit2/src/diff_output.h +15 -8
  156. data/vendor/libgit2/src/diff_tform.c +687 -0
  157. data/vendor/libgit2/src/errors.c +27 -36
  158. data/vendor/libgit2/src/fetch.c +13 -351
  159. data/vendor/libgit2/src/fetch.h +13 -3
  160. data/vendor/libgit2/src/fetchhead.c +295 -0
  161. data/vendor/libgit2/src/fetchhead.h +34 -0
  162. data/vendor/libgit2/src/filebuf.c +42 -15
  163. data/vendor/libgit2/src/filebuf.h +4 -2
  164. data/vendor/libgit2/src/fileops.c +466 -113
  165. data/vendor/libgit2/src/fileops.h +154 -28
  166. data/vendor/libgit2/src/filter.c +3 -75
  167. data/vendor/libgit2/src/filter.h +1 -29
  168. data/vendor/libgit2/src/fnmatch.c +1 -1
  169. data/vendor/libgit2/src/fnmatch.h +1 -1
  170. data/vendor/libgit2/src/global.c +54 -10
  171. data/vendor/libgit2/src/global.h +10 -1
  172. data/vendor/libgit2/src/graph.c +178 -0
  173. data/vendor/libgit2/src/hash.c +25 -52
  174. data/vendor/libgit2/src/hash.h +21 -9
  175. data/vendor/libgit2/src/{sha1/sha1.c → hash/hash_generic.c} +20 -12
  176. data/vendor/libgit2/src/hash/hash_generic.h +24 -0
  177. data/vendor/libgit2/src/hash/hash_openssl.h +45 -0
  178. data/vendor/libgit2/src/hash/hash_win32.c +291 -0
  179. data/vendor/libgit2/src/hash/hash_win32.h +140 -0
  180. data/vendor/libgit2/src/hashsig.c +368 -0
  181. data/vendor/libgit2/src/hashsig.h +72 -0
  182. data/vendor/libgit2/src/ignore.c +22 -15
  183. data/vendor/libgit2/src/ignore.h +6 -1
  184. data/vendor/libgit2/src/index.c +770 -171
  185. data/vendor/libgit2/src/index.h +13 -5
  186. data/vendor/libgit2/src/indexer.c +286 -431
  187. data/vendor/libgit2/src/iterator.c +854 -466
  188. data/vendor/libgit2/src/iterator.h +134 -109
  189. data/vendor/libgit2/src/map.h +1 -1
  190. data/vendor/libgit2/src/merge.c +296 -0
  191. data/vendor/libgit2/src/merge.h +22 -0
  192. data/vendor/libgit2/src/message.c +1 -1
  193. data/vendor/libgit2/src/message.h +1 -1
  194. data/vendor/libgit2/src/mwindow.c +35 -30
  195. data/vendor/libgit2/src/mwindow.h +2 -2
  196. data/vendor/libgit2/src/netops.c +162 -98
  197. data/vendor/libgit2/src/netops.h +50 -15
  198. data/vendor/libgit2/src/notes.c +109 -58
  199. data/vendor/libgit2/src/notes.h +2 -1
  200. data/vendor/libgit2/src/object.c +46 -57
  201. data/vendor/libgit2/src/object.h +1 -8
  202. data/vendor/libgit2/src/odb.c +151 -40
  203. data/vendor/libgit2/src/odb.h +5 -1
  204. data/vendor/libgit2/src/odb_loose.c +4 -5
  205. data/vendor/libgit2/src/odb_pack.c +122 -80
  206. data/vendor/libgit2/src/offmap.h +65 -0
  207. data/vendor/libgit2/src/oid.c +12 -4
  208. data/vendor/libgit2/src/oidmap.h +1 -1
  209. data/vendor/libgit2/src/pack-objects.c +88 -61
  210. data/vendor/libgit2/src/pack-objects.h +8 -8
  211. data/vendor/libgit2/src/pack.c +293 -28
  212. data/vendor/libgit2/src/pack.h +49 -4
  213. data/vendor/libgit2/src/path.c +103 -14
  214. data/vendor/libgit2/src/path.h +23 -7
  215. data/vendor/libgit2/src/pathspec.c +168 -0
  216. data/vendor/libgit2/src/pathspec.h +40 -0
  217. data/vendor/libgit2/src/pool.c +29 -4
  218. data/vendor/libgit2/src/pool.h +8 -1
  219. data/vendor/libgit2/src/posix.c +26 -27
  220. data/vendor/libgit2/src/posix.h +2 -3
  221. data/vendor/libgit2/src/pqueue.c +23 -1
  222. data/vendor/libgit2/src/pqueue.h +23 -1
  223. data/vendor/libgit2/src/push.c +653 -0
  224. data/vendor/libgit2/src/push.h +51 -0
  225. data/vendor/libgit2/src/refdb.c +185 -0
  226. data/vendor/libgit2/src/refdb.h +46 -0
  227. data/vendor/libgit2/src/refdb_fs.c +1024 -0
  228. data/vendor/libgit2/src/refdb_fs.h +15 -0
  229. data/vendor/libgit2/src/reflog.c +77 -45
  230. data/vendor/libgit2/src/reflog.h +1 -3
  231. data/vendor/libgit2/src/refs.c +366 -1326
  232. data/vendor/libgit2/src/refs.h +22 -13
  233. data/vendor/libgit2/src/refspec.c +46 -7
  234. data/vendor/libgit2/src/refspec.h +11 -1
  235. data/vendor/libgit2/src/remote.c +758 -120
  236. data/vendor/libgit2/src/remote.h +10 -5
  237. data/vendor/libgit2/src/repo_template.h +6 -6
  238. data/vendor/libgit2/src/repository.c +315 -96
  239. data/vendor/libgit2/src/repository.h +5 -3
  240. data/vendor/libgit2/src/reset.c +99 -81
  241. data/vendor/libgit2/src/revparse.c +157 -84
  242. data/vendor/libgit2/src/revwalk.c +68 -470
  243. data/vendor/libgit2/src/revwalk.h +44 -0
  244. data/vendor/libgit2/src/sha1_lookup.c +1 -1
  245. data/vendor/libgit2/src/sha1_lookup.h +1 -1
  246. data/vendor/libgit2/src/signature.c +68 -200
  247. data/vendor/libgit2/src/signature.h +1 -1
  248. data/vendor/libgit2/src/stash.c +663 -0
  249. data/vendor/libgit2/src/status.c +101 -79
  250. data/vendor/libgit2/src/strmap.h +1 -1
  251. data/vendor/libgit2/src/submodule.c +67 -51
  252. data/vendor/libgit2/src/submodule.h +1 -1
  253. data/vendor/libgit2/src/tag.c +35 -29
  254. data/vendor/libgit2/src/tag.h +1 -1
  255. data/vendor/libgit2/src/thread-utils.c +1 -1
  256. data/vendor/libgit2/src/thread-utils.h +2 -2
  257. data/vendor/libgit2/src/trace.c +39 -0
  258. data/vendor/libgit2/src/trace.h +56 -0
  259. data/vendor/libgit2/src/transport.c +81 -34
  260. data/vendor/libgit2/src/transports/cred.c +60 -0
  261. data/vendor/libgit2/src/transports/cred_helpers.c +49 -0
  262. data/vendor/libgit2/src/transports/git.c +234 -127
  263. data/vendor/libgit2/src/transports/http.c +761 -433
  264. data/vendor/libgit2/src/transports/local.c +460 -64
  265. data/vendor/libgit2/src/transports/smart.c +345 -0
  266. data/vendor/libgit2/src/transports/smart.h +179 -0
  267. data/vendor/libgit2/src/{pkt.c → transports/smart_pkt.c} +131 -12
  268. data/vendor/libgit2/src/transports/smart_protocol.c +856 -0
  269. data/vendor/libgit2/src/transports/winhttp.c +1136 -0
  270. data/vendor/libgit2/src/tree-cache.c +2 -2
  271. data/vendor/libgit2/src/tree-cache.h +1 -1
  272. data/vendor/libgit2/src/tree.c +239 -166
  273. data/vendor/libgit2/src/tree.h +11 -2
  274. data/vendor/libgit2/src/tsort.c +39 -23
  275. data/vendor/libgit2/src/unix/map.c +1 -1
  276. data/vendor/libgit2/src/unix/posix.h +12 -2
  277. data/vendor/libgit2/src/unix/realpath.c +30 -0
  278. data/vendor/libgit2/src/util.c +250 -13
  279. data/vendor/libgit2/src/util.h +71 -14
  280. data/vendor/libgit2/src/vector.c +123 -60
  281. data/vendor/libgit2/src/vector.h +24 -22
  282. data/vendor/libgit2/src/win32/dir.c +1 -1
  283. data/vendor/libgit2/src/win32/dir.h +1 -1
  284. data/vendor/libgit2/src/win32/error.c +77 -0
  285. data/vendor/libgit2/src/win32/error.h +13 -0
  286. data/vendor/libgit2/src/win32/findfile.c +143 -54
  287. data/vendor/libgit2/src/win32/findfile.h +10 -6
  288. data/vendor/libgit2/src/win32/map.c +1 -1
  289. data/vendor/libgit2/src/win32/mingw-compat.h +1 -1
  290. data/vendor/libgit2/src/win32/msvc-compat.h +10 -1
  291. data/vendor/libgit2/src/win32/posix.h +10 -1
  292. data/vendor/libgit2/src/win32/posix_w32.c +132 -63
  293. data/vendor/libgit2/src/win32/precompiled.c +1 -1
  294. data/vendor/libgit2/src/win32/pthread.c +1 -1
  295. data/vendor/libgit2/src/win32/pthread.h +1 -1
  296. data/vendor/libgit2/src/win32/utf-conv.c +5 -5
  297. data/vendor/libgit2/src/win32/utf-conv.h +3 -3
  298. data/vendor/libgit2/src/win32/version.h +20 -0
  299. metadata +308 -252
  300. data/test/fixtures/testrepo.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  301. data/test/fixtures/testrepo.git/objects/7f/043268ea43ce18e3540acaabf9e090c91965b0 +0 -0
  302. data/test/fixtures/testrepo.git/objects/a3/e05719b428a2d0ed7a55c4ce53dcc5768c6d5e +0 -0
  303. data/test/index_test.rb~ +0 -218
  304. data/vendor/libgit2/src/pkt.h +0 -91
  305. data/vendor/libgit2/src/ppc/sha1.c +0 -70
  306. data/vendor/libgit2/src/ppc/sha1.h +0 -26
  307. data/vendor/libgit2/src/protocol.c +0 -110
  308. data/vendor/libgit2/src/protocol.h +0 -21
  309. data/vendor/libgit2/src/sha1.h +0 -33
  310. data/vendor/libgit2/src/transport.h +0 -148
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -17,8 +17,8 @@
17
17
  struct git_commit {
18
18
  git_object object;
19
19
 
20
- git_vector parent_oids;
21
- git_oid tree_oid;
20
+ git_vector parent_ids;
21
+ git_oid tree_id;
22
22
 
23
23
  git_signature *author;
24
24
  git_signature *committer;
@@ -0,0 +1,194 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+
8
+ #include "commit_list.h"
9
+ #include "common.h"
10
+ #include "revwalk.h"
11
+ #include "pool.h"
12
+ #include "odb.h"
13
+
14
+ int git_commit_list_time_cmp(void *a, void *b)
15
+ {
16
+ git_commit_list_node *commit_a = (git_commit_list_node *)a;
17
+ git_commit_list_node *commit_b = (git_commit_list_node *)b;
18
+
19
+ return (commit_a->time < commit_b->time);
20
+ }
21
+
22
+ git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p)
23
+ {
24
+ git_commit_list *new_list = git__malloc(sizeof(git_commit_list));
25
+ if (new_list != NULL) {
26
+ new_list->item = item;
27
+ new_list->next = *list_p;
28
+ }
29
+ *list_p = new_list;
30
+ return new_list;
31
+ }
32
+
33
+ git_commit_list *git_commit_list_insert_by_date(git_commit_list_node *item, git_commit_list **list_p)
34
+ {
35
+ git_commit_list **pp = list_p;
36
+ git_commit_list *p;
37
+
38
+ while ((p = *pp) != NULL) {
39
+ if (git_commit_list_time_cmp(p->item, item) < 0)
40
+ break;
41
+
42
+ pp = &p->next;
43
+ }
44
+
45
+ return git_commit_list_insert(item, pp);
46
+ }
47
+
48
+ git_commit_list_node *git_commit_list_alloc_node(git_revwalk *walk)
49
+ {
50
+ return (git_commit_list_node *)git_pool_malloc(&walk->commit_pool, COMMIT_ALLOC);
51
+ }
52
+
53
+ static int commit_error(git_commit_list_node *commit, const char *msg)
54
+ {
55
+ char commit_oid[GIT_OID_HEXSZ + 1];
56
+ git_oid_fmt(commit_oid, &commit->oid);
57
+ commit_oid[GIT_OID_HEXSZ] = '\0';
58
+
59
+ giterr_set(GITERR_ODB, "Failed to parse commit %s - %s", commit_oid, msg);
60
+
61
+ return -1;
62
+ }
63
+
64
+ static git_commit_list_node **alloc_parents(
65
+ git_revwalk *walk, git_commit_list_node *commit, size_t n_parents)
66
+ {
67
+ if (n_parents <= PARENTS_PER_COMMIT)
68
+ return (git_commit_list_node **)((char *)commit + sizeof(git_commit_list_node));
69
+
70
+ return (git_commit_list_node **)git_pool_malloc(
71
+ &walk->commit_pool, (uint32_t)(n_parents * sizeof(git_commit_list_node *)));
72
+ }
73
+
74
+
75
+ void git_commit_list_free(git_commit_list **list_p)
76
+ {
77
+ git_commit_list *list = *list_p;
78
+
79
+ if (list == NULL)
80
+ return;
81
+
82
+ while (list) {
83
+ git_commit_list *temp = list;
84
+ list = temp->next;
85
+ git__free(temp);
86
+ }
87
+
88
+ *list_p = NULL;
89
+ }
90
+
91
+ git_commit_list_node *git_commit_list_pop(git_commit_list **stack)
92
+ {
93
+ git_commit_list *top = *stack;
94
+ git_commit_list_node *item = top ? top->item : NULL;
95
+
96
+ if (top) {
97
+ *stack = top->next;
98
+ git__free(top);
99
+ }
100
+ return item;
101
+ }
102
+
103
+ static int commit_quick_parse(git_revwalk *walk, git_commit_list_node *commit, git_rawobj *raw)
104
+ {
105
+ const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1;
106
+ unsigned char *buffer = raw->data;
107
+ unsigned char *buffer_end = buffer + raw->len;
108
+ unsigned char *parents_start, *committer_start;
109
+ int i, parents = 0;
110
+ int commit_time;
111
+
112
+ buffer += strlen("tree ") + GIT_OID_HEXSZ + 1;
113
+
114
+ parents_start = buffer;
115
+ while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", strlen("parent ")) == 0) {
116
+ parents++;
117
+ buffer += parent_len;
118
+ }
119
+
120
+ commit->parents = alloc_parents(walk, commit, parents);
121
+ GITERR_CHECK_ALLOC(commit->parents);
122
+
123
+ buffer = parents_start;
124
+ for (i = 0; i < parents; ++i) {
125
+ git_oid oid;
126
+
127
+ if (git_oid_fromstr(&oid, (char *)buffer + strlen("parent ")) < 0)
128
+ return -1;
129
+
130
+ commit->parents[i] = git_revwalk__commit_lookup(walk, &oid);
131
+ if (commit->parents[i] == NULL)
132
+ return -1;
133
+
134
+ buffer += parent_len;
135
+ }
136
+
137
+ commit->out_degree = (unsigned short)parents;
138
+
139
+ if ((committer_start = buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
140
+ return commit_error(commit, "object is corrupted");
141
+
142
+ buffer++;
143
+
144
+ if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
145
+ return commit_error(commit, "object is corrupted");
146
+
147
+ /* Skip trailing spaces */
148
+ while (buffer > committer_start && git__isspace(*buffer))
149
+ buffer--;
150
+
151
+ /* Seek for the begining of the pack of digits */
152
+ while (buffer > committer_start && git__isdigit(*buffer))
153
+ buffer--;
154
+
155
+ /* Skip potential timezone offset */
156
+ if ((buffer > committer_start) && (*buffer == '+' || *buffer == '-')) {
157
+ buffer--;
158
+
159
+ while (buffer > committer_start && git__isspace(*buffer))
160
+ buffer--;
161
+
162
+ while (buffer > committer_start && git__isdigit(*buffer))
163
+ buffer--;
164
+ }
165
+
166
+ if ((buffer == committer_start) || (git__strtol32(&commit_time, (char *)(buffer + 1), NULL, 10) < 0))
167
+ return commit_error(commit, "cannot parse commit time");
168
+
169
+ commit->time = (time_t)commit_time;
170
+ commit->parsed = 1;
171
+ return 0;
172
+ }
173
+
174
+ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit)
175
+ {
176
+ git_odb_object *obj;
177
+ int error;
178
+
179
+ if (commit->parsed)
180
+ return 0;
181
+
182
+ if ((error = git_odb_read(&obj, walk->odb, &commit->oid)) < 0)
183
+ return error;
184
+
185
+ if (obj->raw.type != GIT_OBJ_COMMIT) {
186
+ giterr_set(GITERR_INVALID, "Object is no commit object");
187
+ error = -1;
188
+ } else
189
+ error = commit_quick_parse(walk, commit, &obj->raw);
190
+
191
+ git_odb_object_free(obj);
192
+ return error;
193
+ }
194
+
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+ #ifndef INCLUDE_commit_list_h__
8
+ #define INCLUDE_commit_list_h__
9
+
10
+ #include "git2/oid.h"
11
+
12
+ #define PARENT1 (1 << 0)
13
+ #define PARENT2 (1 << 1)
14
+ #define RESULT (1 << 2)
15
+ #define STALE (1 << 3)
16
+
17
+ #define PARENTS_PER_COMMIT 2
18
+ #define COMMIT_ALLOC \
19
+ (sizeof(git_commit_list_node) + PARENTS_PER_COMMIT * sizeof(git_commit_list_node *))
20
+
21
+ typedef struct git_commit_list_node {
22
+ git_oid oid;
23
+ uint32_t time;
24
+ unsigned int seen:1,
25
+ uninteresting:1,
26
+ topo_delay:1,
27
+ parsed:1,
28
+ flags : 4;
29
+
30
+ unsigned short in_degree;
31
+ unsigned short out_degree;
32
+
33
+ struct git_commit_list_node **parents;
34
+ } git_commit_list_node;
35
+
36
+ typedef struct git_commit_list {
37
+ git_commit_list_node *item;
38
+ struct git_commit_list *next;
39
+ } git_commit_list;
40
+
41
+ git_commit_list_node *git_commit_list_alloc_node(git_revwalk *walk);
42
+ int git_commit_list_time_cmp(void *a, void *b);
43
+ void git_commit_list_free(git_commit_list **list_p);
44
+ git_commit_list *git_commit_list_insert(git_commit_list_node *item, git_commit_list **list_p);
45
+ git_commit_list *git_commit_list_insert_by_date(git_commit_list_node *item, git_commit_list **list_p);
46
+ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit);
47
+ git_commit_list_node *git_commit_list_pop(git_commit_list **stack);
48
+
49
+ #endif
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -28,18 +28,20 @@
28
28
  # include <windows.h>
29
29
  # include "win32/msvc-compat.h"
30
30
  # include "win32/mingw-compat.h"
31
+ # include "win32/error.h"
32
+ # include "win32/version.h"
31
33
  # ifdef GIT_THREADS
32
34
  # include "win32/pthread.h"
33
- #endif
34
-
35
- # define snprintf _snprintf
35
+ # endif
36
36
 
37
37
  #else
38
- # include <unistd.h>
39
38
 
39
+ # include <unistd.h>
40
40
  # ifdef GIT_THREADS
41
41
  # include <pthread.h>
42
42
  # endif
43
+ #define GIT_STDLIB_CALL
44
+
43
45
  #endif
44
46
 
45
47
  #include "git2/types.h"
@@ -54,6 +56,12 @@
54
56
  */
55
57
  #define GITERR_CHECK_ALLOC(ptr) if (ptr == NULL) { return -1; }
56
58
 
59
+ /**
60
+ * Check a return value and propogate result if non-zero.
61
+ */
62
+ #define GITERR_CHECK_ERROR(code) \
63
+ do { int _err = (code); if (_err < 0) return _err; } while (0)
64
+
57
65
  /**
58
66
  * Set the error message for this thread, formatting as needed.
59
67
  */
@@ -61,15 +69,41 @@ void giterr_set(int error_class, const char *string, ...);
61
69
 
62
70
  /**
63
71
  * Set the error message for a regex failure, using the internal regex
64
- * error code lookup.
72
+ * error code lookup and return a libgit error code.
65
73
  */
66
- void giterr_set_regex(const regex_t *regex, int error_code);
74
+ int giterr_set_regex(const regex_t *regex, int error_code);
75
+
76
+ /**
77
+ * Check a versioned structure for validity
78
+ */
79
+ GIT_INLINE(int) giterr__check_version(const void *structure, unsigned int expected_max, const char *name)
80
+ {
81
+ unsigned int actual;
82
+
83
+ if (!structure)
84
+ return 0;
85
+
86
+ actual = *(const unsigned int*)structure;
87
+ if (actual > 0 && actual <= expected_max)
88
+ return 0;
89
+
90
+ giterr_set(GITERR_INVALID, "Invalid version %d on %s", actual, name);
91
+ return -1;
92
+ }
93
+ #define GITERR_CHECK_VERSION(S,V,N) if (giterr__check_version(S,V,N) < 0) return -1
94
+
95
+ /**
96
+ * Initialize a structure with a version.
97
+ */
98
+ GIT_INLINE(void) git__init_structure(void *structure, size_t len, unsigned int version)
99
+ {
100
+ memset(structure, 0, len);
101
+ *((int*)structure) = version;
102
+ }
103
+ #define GIT_INIT_STRUCTURE(S,V) git__init_structure(S, sizeof(*S), V)
67
104
 
68
105
  /* NOTE: other giterr functions are in the public errors.h header file */
69
106
 
70
107
  #include "util.h"
71
108
 
72
- typedef struct git_transport git_transport;
73
- typedef struct gitno_buffer gitno_buffer;
74
-
75
109
  #endif /* INCLUDE_common_h__ */
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2012 the libgit2 contributors
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
3
  *
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
@@ -10,6 +10,8 @@
10
10
  #include "config.h"
11
11
  #include "git2/config.h"
12
12
  #include "vector.h"
13
+ #include "buf_text.h"
14
+ #include "config_file.h"
13
15
  #if GIT_WIN32
14
16
  # include <windows.h>
15
17
  #endif
@@ -19,13 +21,13 @@
19
21
  typedef struct {
20
22
  git_refcount rc;
21
23
 
22
- git_config_file *file;
24
+ git_config_backend *file;
23
25
  unsigned int level;
24
26
  } file_internal;
25
27
 
26
28
  static void file_internal_free(file_internal *internal)
27
29
  {
28
- git_config_file *file;
30
+ git_config_backend *file;
29
31
 
30
32
  file = internal->file;
31
33
  file->free(file);
@@ -34,7 +36,7 @@ static void file_internal_free(file_internal *internal)
34
36
 
35
37
  static void config_free(git_config *cfg)
36
38
  {
37
- unsigned int i;
39
+ size_t i;
38
40
  file_internal *internal;
39
41
 
40
42
  for(i = 0; i < cfg->files.length; ++i){
@@ -87,13 +89,20 @@ int git_config_add_file_ondisk(
87
89
  unsigned int level,
88
90
  int force)
89
91
  {
90
- git_config_file *file = NULL;
92
+ git_config_backend *file = NULL;
91
93
  int res;
92
94
 
95
+ assert(cfg && path);
96
+
97
+ if (!git_path_isfile(path)) {
98
+ giterr_set(GITERR_CONFIG, "Cannot find config file '%s'", path);
99
+ return GIT_ENOTFOUND;
100
+ }
101
+
93
102
  if (git_config_file__ondisk(&file, path) < 0)
94
103
  return -1;
95
104
 
96
- if ((res = git_config_add_file(cfg, file, level, force)) < 0) {
105
+ if ((res = git_config_add_backend(cfg, file, level, force)) < 0) {
97
106
  /*
98
107
  * free manually; the file is not owned by the config
99
108
  * instance yet and will not be freed on cleanup
@@ -105,30 +114,33 @@ int git_config_add_file_ondisk(
105
114
  return 0;
106
115
  }
107
116
 
108
- int git_config_open_ondisk(git_config **cfg, const char *path)
117
+ int git_config_open_ondisk(git_config **out, const char *path)
109
118
  {
110
- if (git_config_new(cfg) < 0)
111
- return -1;
119
+ int error;
120
+ git_config *config;
112
121
 
113
- if (git_config_add_file_ondisk(*cfg, path, GIT_CONFIG_LEVEL_LOCAL, 0) < 0) {
114
- git_config_free(*cfg);
122
+ *out = NULL;
123
+
124
+ if (git_config_new(&config) < 0)
115
125
  return -1;
116
- }
117
126
 
118
- return 0;
127
+ if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0)
128
+ git_config_free(config);
129
+ else
130
+ *out = config;
131
+
132
+ return error;
119
133
  }
120
134
 
121
135
  static int find_internal_file_by_level(
122
136
  file_internal **internal_out,
123
- git_config *cfg,
137
+ const git_config *cfg,
124
138
  int level)
125
139
  {
126
140
  int pos = -1;
127
141
  file_internal *internal;
128
142
  unsigned int i;
129
143
 
130
- assert(cfg->files.length);
131
-
132
144
  /* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config file
133
145
  * which has the highest level. As config files are stored in a vector
134
146
  * sorted by decreasing order of level, getting the file at position 0
@@ -214,7 +226,7 @@ static int git_config__add_internal(
214
226
 
215
227
  int git_config_open_level(
216
228
  git_config **cfg_out,
217
- git_config *cfg_parent,
229
+ const git_config *cfg_parent,
218
230
  unsigned int level)
219
231
  {
220
232
  git_config *cfg;
@@ -237,9 +249,9 @@ int git_config_open_level(
237
249
  return 0;
238
250
  }
239
251
 
240
- int git_config_add_file(
252
+ int git_config_add_backend(
241
253
  git_config *cfg,
242
- git_config_file *file,
254
+ git_config_backend *file,
243
255
  unsigned int level,
244
256
  int force)
245
257
  {
@@ -248,6 +260,8 @@ int git_config_add_file(
248
260
 
249
261
  assert(cfg && file);
250
262
 
263
+ GITERR_CHECK_VERSION(file, GIT_CONFIG_BACKEND_VERSION, "git_config_backend");
264
+
251
265
  if ((result = file->open(file, level)) < 0)
252
266
  return result;
253
267
 
@@ -267,39 +281,53 @@ int git_config_add_file(
267
281
  return 0;
268
282
  }
269
283
 
284
+ int git_config_refresh(git_config *cfg)
285
+ {
286
+ int error = 0;
287
+ size_t i;
288
+
289
+ for (i = 0; i < cfg->files.length && !error; ++i) {
290
+ file_internal *internal = git_vector_get(&cfg->files, i);
291
+ git_config_backend *file = internal->file;
292
+ error = file->refresh(file);
293
+ }
294
+
295
+ return error;
296
+ }
297
+
270
298
  /*
271
299
  * Loop over all the variables
272
300
  */
273
301
 
274
302
  int git_config_foreach(
275
- git_config *cfg, int (*fn)(const git_config_entry *, void *), void *data)
303
+ const git_config *cfg, git_config_foreach_cb cb, void *payload)
276
304
  {
277
- return git_config_foreach_match(cfg, NULL, fn, data);
305
+ return git_config_foreach_match(cfg, NULL, cb, payload);
278
306
  }
279
307
 
280
308
  int git_config_foreach_match(
281
- git_config *cfg,
309
+ const git_config *cfg,
282
310
  const char *regexp,
283
- int (*fn)(const git_config_entry *, void *),
284
- void *data)
311
+ git_config_foreach_cb cb,
312
+ void *payload)
285
313
  {
286
314
  int ret = 0;
287
- unsigned int i;
315
+ size_t i;
288
316
  file_internal *internal;
289
- git_config_file *file;
317
+ git_config_backend *file;
290
318
 
291
319
  for (i = 0; i < cfg->files.length && ret == 0; ++i) {
292
320
  internal = git_vector_get(&cfg->files, i);
293
321
  file = internal->file;
294
- ret = file->foreach(file, regexp, fn, data);
322
+ ret = file->foreach(file, regexp, cb, payload);
295
323
  }
296
324
 
297
325
  return ret;
298
326
  }
299
327
 
300
- int git_config_delete(git_config *cfg, const char *name)
328
+ int git_config_delete_entry(git_config *cfg, const char *name)
301
329
  {
302
- git_config_file *file;
330
+ git_config_backend *file;
303
331
  file_internal *internal;
304
332
 
305
333
  internal = git_vector_get(&cfg->files, 0);
@@ -331,9 +359,14 @@ int git_config_set_bool(git_config *cfg, const char *name, int value)
331
359
 
332
360
  int git_config_set_string(git_config *cfg, const char *name, const char *value)
333
361
  {
334
- git_config_file *file;
362
+ git_config_backend *file;
335
363
  file_internal *internal;
336
364
 
365
+ if (!value) {
366
+ giterr_set(GITERR_CONFIG, "The value to set cannot be NULL");
367
+ return -1;
368
+ }
369
+
337
370
  internal = git_vector_get(&cfg->files, 0);
338
371
  file = internal->file;
339
372
 
@@ -345,9 +378,9 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value)
345
378
  ***********/
346
379
  int git_config_get_mapped(
347
380
  int *out,
348
- git_config *cfg,
381
+ const git_config *cfg,
349
382
  const char *name,
350
- git_cvar_map *maps,
383
+ const git_cvar_map *maps,
351
384
  size_t map_n)
352
385
  {
353
386
  const char *value;
@@ -359,7 +392,7 @@ int git_config_get_mapped(
359
392
  return git_config_lookup_map_value(out, maps, map_n, value);
360
393
  }
361
394
 
362
- int git_config_get_int64(int64_t *out, git_config *cfg, const char *name)
395
+ int git_config_get_int64(int64_t *out, const git_config *cfg, const char *name)
363
396
  {
364
397
  const char *value;
365
398
  int ret;
@@ -370,7 +403,7 @@ int git_config_get_int64(int64_t *out, git_config *cfg, const char *name)
370
403
  return git_config_parse_int64(out, value);
371
404
  }
372
405
 
373
- int git_config_get_int32(int32_t *out, git_config *cfg, const char *name)
406
+ int git_config_get_int32(int32_t *out, const git_config *cfg, const char *name)
374
407
  {
375
408
  const char *value;
376
409
  int ret;
@@ -381,38 +414,23 @@ int git_config_get_int32(int32_t *out, git_config *cfg, const char *name)
381
414
  return git_config_parse_int32(out, value);
382
415
  }
383
416
 
384
- int git_config_get_bool(int *out, git_config *cfg, const char *name)
385
- {
386
- const char *value;
387
- int ret;
388
-
389
- if ((ret = git_config_get_string(&value, cfg, name)) < 0)
390
- return ret;
391
-
392
- return git_config_parse_bool(out, value);
393
- }
394
-
395
- static int get_string_at_file(const char **out, git_config_file *file, const char *name)
417
+ static int get_string_at_file(const char **out, const git_config_backend *file, const char *name)
396
418
  {
397
419
  const git_config_entry *entry;
398
420
  int res;
399
421
 
400
- *out = NULL;
401
-
402
422
  res = file->get(file, name, &entry);
403
- if (res != GIT_ENOTFOUND)
423
+ if (!res)
404
424
  *out = entry->value;
405
425
 
406
426
  return res;
407
427
  }
408
428
 
409
- int git_config_get_string(const char **out, git_config *cfg, const char *name)
429
+ static int get_string(const char **out, const git_config *cfg, const char *name)
410
430
  {
411
431
  file_internal *internal;
412
432
  unsigned int i;
413
433
 
414
- assert(cfg->files.length);
415
-
416
434
  git_vector_foreach(&cfg->files, i, internal) {
417
435
  int res = get_string_at_file(out, internal->file, name);
418
436
 
@@ -423,17 +441,38 @@ int git_config_get_string(const char **out, git_config *cfg, const char *name)
423
441
  return GIT_ENOTFOUND;
424
442
  }
425
443
 
426
- int git_config_get_config_entry(const git_config_entry **out, git_config *cfg, const char *name)
444
+ int git_config_get_bool(int *out, const git_config *cfg, const char *name)
445
+ {
446
+ const char *value = NULL;
447
+ int ret;
448
+
449
+ if ((ret = get_string(&value, cfg, name)) < 0)
450
+ return ret;
451
+
452
+ return git_config_parse_bool(out, value);
453
+ }
454
+
455
+ int git_config_get_string(const char **out, const git_config *cfg, const char *name)
456
+ {
457
+ int ret;
458
+ const char *str = NULL;
459
+
460
+ if ((ret = get_string(&str, cfg, name)) < 0)
461
+ return ret;
462
+
463
+ *out = str == NULL ? "" : str;
464
+ return 0;
465
+ }
466
+
467
+ int git_config_get_entry(const git_config_entry **out, const git_config *cfg, const char *name)
427
468
  {
428
469
  file_internal *internal;
429
470
  unsigned int i;
430
471
 
431
- assert(cfg->files.length);
432
-
433
472
  *out = NULL;
434
473
 
435
474
  git_vector_foreach(&cfg->files, i, internal) {
436
- git_config_file *file = internal->file;
475
+ git_config_backend *file = internal->file;
437
476
  int ret = file->get(file, name, out);
438
477
  if (ret != GIT_ENOTFOUND)
439
478
  return ret;
@@ -442,16 +481,14 @@ int git_config_get_config_entry(const git_config_entry **out, git_config *cfg, c
442
481
  return GIT_ENOTFOUND;
443
482
  }
444
483
 
445
- int git_config_get_multivar(git_config *cfg, const char *name, const char *regexp,
446
- int (*fn)(const git_config_entry *entry, void *data), void *data)
484
+ int git_config_get_multivar(const git_config *cfg, const char *name, const char *regexp,
485
+ git_config_foreach_cb cb, void *payload)
447
486
  {
448
487
  file_internal *internal;
449
- git_config_file *file;
488
+ git_config_backend *file;
450
489
  int ret = GIT_ENOTFOUND;
451
490
  size_t i;
452
491
 
453
- assert(cfg->files.length);
454
-
455
492
  /*
456
493
  * This loop runs the "wrong" way 'round because we need to
457
494
  * look at every value from the most general to most specific
@@ -459,7 +496,7 @@ int git_config_get_multivar(git_config *cfg, const char *name, const char *regex
459
496
  for (i = cfg->files.length; i > 0; --i) {
460
497
  internal = git_vector_get(&cfg->files, i - 1);
461
498
  file = internal->file;
462
- ret = file->get_multivar(file, name, regexp, fn, data);
499
+ ret = file->get_multivar(file, name, regexp, cb, payload);
463
500
  if (ret < 0 && ret != GIT_ENOTFOUND)
464
501
  return ret;
465
502
  }
@@ -469,7 +506,7 @@ int git_config_get_multivar(git_config *cfg, const char *name, const char *regex
469
506
 
470
507
  int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
471
508
  {
472
- git_config_file *file;
509
+ git_config_backend *file;
473
510
  file_internal *internal;
474
511
 
475
512
  internal = git_vector_get(&cfg->files, 0);
@@ -478,62 +515,48 @@ int git_config_set_multivar(git_config *cfg, const char *name, const char *regex
478
515
  return file->set_multivar(file, name, regexp, value);
479
516
  }
480
517
 
481
- int git_config_find_global_r(git_buf *path)
518
+ static int git_config__find_file_to_path(
519
+ char *out, size_t outlen, int (*find)(git_buf *buf))
482
520
  {
483
- int error = git_futils_find_global_file(path, GIT_CONFIG_FILENAME);
521
+ int error = 0;
522
+ git_buf path = GIT_BUF_INIT;
484
523
 
524
+ if ((error = find(&path)) < 0)
525
+ goto done;
526
+
527
+ if (path.size >= outlen) {
528
+ giterr_set(GITERR_NOMEMORY, "Buffer is too short for the path");
529
+ error = GIT_EBUFS;
530
+ goto done;
531
+ }
532
+
533
+ git_buf_copy_cstr(out, outlen, &path);
534
+
535
+ done:
536
+ git_buf_free(&path);
485
537
  return error;
486
538
  }
487
539
 
488
- int git_config_find_xdg_r(git_buf *path)
540
+ int git_config_find_global_r(git_buf *path)
489
541
  {
490
- int error = git_futils_find_global_file(path, GIT_CONFIG_FILENAME_ALT);
491
-
492
- return error;
542
+ return git_futils_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
493
543
  }
494
544
 
495
545
  int git_config_find_global(char *global_config_path, size_t length)
496
546
  {
497
- git_buf path = GIT_BUF_INIT;
498
- int ret = git_config_find_global_r(&path);
499
-
500
- if (ret < 0) {
501
- git_buf_free(&path);
502
- return ret;
503
- }
504
-
505
- if (path.size >= length) {
506
- git_buf_free(&path);
507
- giterr_set(GITERR_NOMEMORY,
508
- "Path is to long to fit on the given buffer");
509
- return -1;
510
- }
547
+ return git_config__find_file_to_path(
548
+ global_config_path, length, git_config_find_global_r);
549
+ }
511
550
 
512
- git_buf_copy_cstr(global_config_path, length, &path);
513
- git_buf_free(&path);
514
- return 0;
551
+ int git_config_find_xdg_r(git_buf *path)
552
+ {
553
+ return git_futils_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
515
554
  }
516
555
 
517
556
  int git_config_find_xdg(char *xdg_config_path, size_t length)
518
557
  {
519
- git_buf path = GIT_BUF_INIT;
520
- int ret = git_config_find_xdg_r(&path);
521
-
522
- if (ret < 0) {
523
- git_buf_free(&path);
524
- return ret;
525
- }
526
-
527
- if (path.size >= length) {
528
- git_buf_free(&path);
529
- giterr_set(GITERR_NOMEMORY,
530
- "Path is to long to fit on the given buffer");
531
- return -1;
532
- }
533
-
534
- git_buf_copy_cstr(xdg_config_path, length, &path);
535
- git_buf_free(&path);
536
- return 0;
558
+ return git_config__find_file_to_path(
559
+ xdg_config_path, length, git_config_find_xdg_r);
537
560
  }
538
561
 
539
562
  int git_config_find_system_r(git_buf *path)
@@ -543,24 +566,8 @@ int git_config_find_system_r(git_buf *path)
543
566
 
544
567
  int git_config_find_system(char *system_config_path, size_t length)
545
568
  {
546
- git_buf path = GIT_BUF_INIT;
547
- int ret = git_config_find_system_r(&path);
548
-
549
- if (ret < 0) {
550
- git_buf_free(&path);
551
- return ret;
552
- }
553
-
554
- if (path.size >= length) {
555
- git_buf_free(&path);
556
- giterr_set(GITERR_NOMEMORY,
557
- "Path is to long to fit on the given buffer");
558
- return -1;
559
- }
560
-
561
- git_buf_copy_cstr(system_config_path, length, &path);
562
- git_buf_free(&path);
563
- return 0;
569
+ return git_config__find_file_to_path(
570
+ system_config_path, length, git_config_find_system_r);
564
571
  }
565
572
 
566
573
  int git_config_open_default(git_config **out)
@@ -600,7 +607,7 @@ int git_config_open_default(git_config **out)
600
607
  ***********/
601
608
  int git_config_lookup_map_value(
602
609
  int *out,
603
- git_cvar_map *maps,
610
+ const git_cvar_map *maps,
604
611
  size_t map_n,
605
612
  const char *value)
606
613
  {
@@ -610,7 +617,7 @@ int git_config_lookup_map_value(
610
617
  goto fail_parse;
611
618
 
612
619
  for (i = 0; i < map_n; ++i) {
613
- git_cvar_map *m = maps + i;
620
+ const git_cvar_map *m = maps + i;
614
621
 
615
622
  switch (m->cvar_type) {
616
623
  case GIT_CVAR_FALSE:
@@ -720,3 +727,83 @@ fail_parse:
720
727
  giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value);
721
728
  return -1;
722
729
  }
730
+
731
+ struct rename_data {
732
+ git_config *config;
733
+ git_buf *name;
734
+ size_t old_len;
735
+ int actual_error;
736
+ };
737
+
738
+ static int rename_config_entries_cb(
739
+ const git_config_entry *entry,
740
+ void *payload)
741
+ {
742
+ int error = 0;
743
+ struct rename_data *data = (struct rename_data *)payload;
744
+ size_t base_len = git_buf_len(data->name);
745
+
746
+ if (base_len > 0 &&
747
+ !(error = git_buf_puts(data->name, entry->name + data->old_len)))
748
+ {
749
+ error = git_config_set_string(
750
+ data->config, git_buf_cstr(data->name), entry->value);
751
+
752
+ git_buf_truncate(data->name, base_len);
753
+ }
754
+
755
+ if (!error)
756
+ error = git_config_delete_entry(data->config, entry->name);
757
+
758
+ data->actual_error = error; /* preserve actual error code */
759
+
760
+ return error;
761
+ }
762
+
763
+ int git_config_rename_section(
764
+ git_repository *repo,
765
+ const char *old_section_name,
766
+ const char *new_section_name)
767
+ {
768
+ git_config *config;
769
+ git_buf pattern = GIT_BUF_INIT, replace = GIT_BUF_INIT;
770
+ int error = 0;
771
+ struct rename_data data;
772
+
773
+ git_buf_text_puts_escape_regex(&pattern, old_section_name);
774
+
775
+ if ((error = git_buf_puts(&pattern, "\\..+")) < 0)
776
+ goto cleanup;
777
+
778
+ if ((error = git_repository_config__weakptr(&config, repo)) < 0)
779
+ goto cleanup;
780
+
781
+ data.config = config;
782
+ data.name = &replace;
783
+ data.old_len = strlen(old_section_name) + 1;
784
+ data.actual_error = 0;
785
+
786
+ if ((error = git_buf_join(&replace, '.', new_section_name, "")) < 0)
787
+ goto cleanup;
788
+
789
+ if (new_section_name != NULL &&
790
+ (error = git_config_file_normalize_section(
791
+ replace.ptr, strchr(replace.ptr, '.'))) < 0)
792
+ {
793
+ giterr_set(
794
+ GITERR_CONFIG, "Invalid config section '%s'", new_section_name);
795
+ goto cleanup;
796
+ }
797
+
798
+ error = git_config_foreach_match(
799
+ config, git_buf_cstr(&pattern), rename_config_entries_cb, &data);
800
+
801
+ if (error == GIT_EUSER)
802
+ error = data.actual_error;
803
+
804
+ cleanup:
805
+ git_buf_free(&pattern);
806
+ git_buf_free(&replace);
807
+
808
+ return error;
809
+ }