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.
@@ -104,7 +104,7 @@ static int read_tree_internal(git_tree_cache **out,
104
104
  tree->name[name_len] = '\0';
105
105
 
106
106
  /* Blank-terminated ASCII decimal number of entries in this tree */
107
- if (git__strtol32(&count, buffer, &buffer, 10) < 0 || count < -1)
107
+ if (git__strtol32(&count, buffer, &buffer, 10) < 0)
108
108
  goto corrupted;
109
109
 
110
110
  tree->entries = count;
@@ -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.
@@ -18,25 +18,65 @@ static bool valid_filemode(const int filemode)
18
18
  {
19
19
  return (filemode == GIT_FILEMODE_TREE
20
20
  || filemode == GIT_FILEMODE_BLOB
21
- || filemode == GIT_FILEMODE_BLOB_GROUP_WRITABLE
22
21
  || filemode == GIT_FILEMODE_BLOB_EXECUTABLE
23
22
  || filemode == GIT_FILEMODE_LINK
24
23
  || filemode == GIT_FILEMODE_COMMIT);
25
24
  }
26
25
 
26
+ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
27
+ {
28
+ /* Tree bits set, but it's not a commit */
29
+ if (filemode & GIT_FILEMODE_TREE && !(filemode & 0100000))
30
+ return GIT_FILEMODE_TREE;
31
+
32
+ /* If any of the x bits is set */
33
+ if (filemode & 0111)
34
+ return GIT_FILEMODE_BLOB_EXECUTABLE;
35
+
36
+ /* 16XXXX means commit */
37
+ if ((filemode & GIT_FILEMODE_COMMIT) == GIT_FILEMODE_COMMIT)
38
+ return GIT_FILEMODE_COMMIT;
39
+
40
+ /* 12XXXX means commit */
41
+ if ((filemode & GIT_FILEMODE_LINK) == GIT_FILEMODE_LINK)
42
+ return GIT_FILEMODE_LINK;
43
+
44
+ /* Otherwise, return a blob */
45
+ return GIT_FILEMODE_BLOB;
46
+ }
47
+
27
48
  static int valid_entry_name(const char *filename)
28
49
  {
29
- return *filename != '\0' && strchr(filename, '/') == NULL;
50
+ return *filename != '\0' &&
51
+ strchr(filename, '/') == NULL &&
52
+ (*filename != '.' ||
53
+ (strcmp(filename, ".") != 0 &&
54
+ strcmp(filename, "..") != 0 &&
55
+ strcmp(filename, DOT_GIT) != 0));
30
56
  }
31
57
 
32
58
  static int entry_sort_cmp(const void *a, const void *b)
33
59
  {
34
- const git_tree_entry *entry_a = (const git_tree_entry *)(a);
35
- const git_tree_entry *entry_b = (const git_tree_entry *)(b);
60
+ const git_tree_entry *e1 = (const git_tree_entry *)a;
61
+ const git_tree_entry *e2 = (const git_tree_entry *)b;
36
62
 
37
63
  return git_path_cmp(
38
- entry_a->filename, entry_a->filename_len, git_tree_entry__is_tree(entry_a),
39
- entry_b->filename, entry_b->filename_len, git_tree_entry__is_tree(entry_b));
64
+ e1->filename, e1->filename_len, git_tree_entry__is_tree(e1),
65
+ e2->filename, e2->filename_len, git_tree_entry__is_tree(e2),
66
+ git__strncmp);
67
+ }
68
+
69
+ int git_tree_entry_cmp(const git_tree_entry *e1, const git_tree_entry *e2)
70
+ {
71
+ return entry_sort_cmp(e1, e2);
72
+ }
73
+
74
+ int git_tree_entry_icmp(const git_tree_entry *e1, const git_tree_entry *e2)
75
+ {
76
+ return git_path_cmp(
77
+ e1->filename, e1->filename_len, git_tree_entry__is_tree(e1),
78
+ e2->filename, e2->filename_len, git_tree_entry__is_tree(e2),
79
+ git__strncasecmp);
40
80
  }
41
81
 
42
82
  static git_tree_entry *alloc_entry(const char *filename)
@@ -96,46 +136,57 @@ static int homing_search_cmp(const void *key, const void *array_member)
96
136
  * ambiguous because of folder vs file sorting, we look linearly
97
137
  * around the area for our target file.
98
138
  */
99
- static int tree_key_search(git_vector *entries, const char *filename, size_t filename_len)
139
+ static int tree_key_search(
140
+ size_t *at_pos, git_vector *entries, const char *filename, size_t filename_len)
100
141
  {
101
142
  struct tree_key_search ksearch;
102
143
  const git_tree_entry *entry;
103
-
104
- int homing, i;
144
+ size_t homing, i;
105
145
 
106
146
  ksearch.filename = filename;
107
147
  ksearch.filename_len = filename_len;
108
148
 
109
149
  /* Initial homing search; find an entry on the tree with
110
150
  * the same prefix as the filename we're looking for */
111
- homing = git_vector_bsearch2(entries, &homing_search_cmp, &ksearch);
112
- if (homing < 0)
113
- return homing;
151
+ if (git_vector_bsearch2(&homing, entries, &homing_search_cmp, &ksearch) < 0)
152
+ return GIT_ENOTFOUND;
114
153
 
115
154
  /* We found a common prefix. Look forward as long as
116
155
  * there are entries that share the common prefix */
117
- for (i = homing; i < (int)entries->length; ++i) {
156
+ for (i = homing; i < entries->length; ++i) {
118
157
  entry = entries->contents[i];
119
158
 
120
159
  if (homing_search_cmp(&ksearch, entry) < 0)
121
160
  break;
122
161
 
123
162
  if (entry->filename_len == filename_len &&
124
- memcmp(filename, entry->filename, filename_len) == 0)
125
- return i;
163
+ memcmp(filename, entry->filename, filename_len) == 0) {
164
+ if (at_pos)
165
+ *at_pos = i;
166
+
167
+ return 0;
168
+ }
126
169
  }
127
170
 
128
171
  /* If we haven't found our filename yet, look backwards
129
172
  * too as long as we have entries with the same prefix */
130
- for (i = homing - 1; i >= 0; --i) {
131
- entry = entries->contents[i];
173
+ if (homing > 0) {
174
+ i = homing - 1;
132
175
 
133
- if (homing_search_cmp(&ksearch, entry) > 0)
134
- break;
176
+ do {
177
+ entry = entries->contents[i];
135
178
 
136
- if (entry->filename_len == filename_len &&
137
- memcmp(filename, entry->filename, filename_len) == 0)
138
- return i;
179
+ if (homing_search_cmp(&ksearch, entry) > 0)
180
+ break;
181
+
182
+ if (entry->filename_len == filename_len &&
183
+ memcmp(filename, entry->filename, filename_len) == 0) {
184
+ if (at_pos)
185
+ *at_pos = i;
186
+
187
+ return 0;
188
+ }
189
+ } while (i-- > 0);
139
190
  }
140
191
 
141
192
  /* The filename doesn't exist at all */
@@ -164,25 +215,30 @@ git_tree_entry *git_tree_entry_dup(const git_tree_entry *entry)
164
215
  return NULL;
165
216
 
166
217
  memcpy(copy, entry, total_size);
218
+
167
219
  return copy;
168
220
  }
169
221
 
170
222
  void git_tree__free(git_tree *tree)
171
223
  {
172
- unsigned int i;
224
+ size_t i;
225
+ git_tree_entry *e;
173
226
 
174
- for (i = 0; i < tree->entries.length; ++i) {
175
- git_tree_entry *e = git_vector_get(&tree->entries, i);
227
+ git_vector_foreach(&tree->entries, i, e)
176
228
  git_tree_entry_free(e);
177
- }
178
229
 
179
230
  git_vector_free(&tree->entries);
180
231
  git__free(tree);
181
232
  }
182
233
 
183
- const git_oid *git_tree_id(const git_tree *c)
234
+ const git_oid *git_tree_id(const git_tree *t)
184
235
  {
185
- return git_object_id((const git_object *)c);
236
+ return git_object_id((const git_object *)t);
237
+ }
238
+
239
+ git_repository *git_tree_owner(const git_tree *t)
240
+ {
241
+ return git_object_owner((const git_object *)t);
186
242
  }
187
243
 
188
244
  git_filemode_t git_tree_entry_filemode(const git_tree_entry *entry)
@@ -223,31 +279,36 @@ int git_tree_entry_to_object(
223
279
  return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJ_ANY);
224
280
  }
225
281
 
226
- static git_tree_entry *entry_fromname(git_tree *tree, const char *name, size_t name_len)
282
+ static const git_tree_entry *entry_fromname(
283
+ git_tree *tree, const char *name, size_t name_len)
227
284
  {
228
- int idx = tree_key_search(&tree->entries, name, name_len);
229
- if (idx < 0)
285
+ size_t idx;
286
+
287
+ if (tree_key_search(&idx, &tree->entries, name, name_len) < 0)
230
288
  return NULL;
231
289
 
232
290
  return git_vector_get(&tree->entries, idx);
233
291
  }
234
292
 
235
- const git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
293
+ const git_tree_entry *git_tree_entry_byname(
294
+ git_tree *tree, const char *filename)
236
295
  {
237
296
  assert(tree && filename);
238
297
  return entry_fromname(tree, filename, strlen(filename));
239
298
  }
240
299
 
241
- const git_tree_entry *git_tree_entry_byindex(git_tree *tree, size_t idx)
300
+ const git_tree_entry *git_tree_entry_byindex(
301
+ git_tree *tree, size_t idx)
242
302
  {
243
303
  assert(tree);
244
304
  return git_vector_get(&tree->entries, idx);
245
305
  }
246
306
 
247
- const git_tree_entry *git_tree_entry_byoid(git_tree *tree, const git_oid *oid)
307
+ const git_tree_entry *git_tree_entry_byoid(
308
+ const git_tree *tree, const git_oid *oid)
248
309
  {
249
- unsigned int i;
250
- git_tree_entry *e;
310
+ size_t i;
311
+ const git_tree_entry *e;
251
312
 
252
313
  assert(tree);
253
314
 
@@ -263,13 +324,16 @@ int git_tree__prefix_position(git_tree *tree, const char *path)
263
324
  {
264
325
  git_vector *entries = &tree->entries;
265
326
  struct tree_key_search ksearch;
266
- unsigned int at_pos;
327
+ size_t at_pos;
328
+
329
+ if (!path)
330
+ return 0;
267
331
 
268
332
  ksearch.filename = path;
269
333
  ksearch.filename_len = strlen(path);
270
334
 
271
335
  /* Find tree entry with appropriate prefix */
272
- git_vector_bsearch3(&at_pos, entries, &homing_search_cmp, &ksearch);
336
+ git_vector_bsearch2(&at_pos, entries, &homing_search_cmp, &ksearch);
273
337
 
274
338
  for (; at_pos < entries->length; ++at_pos) {
275
339
  const git_tree_entry *entry = entries->contents[at_pos];
@@ -283,18 +347,27 @@ int git_tree__prefix_position(git_tree *tree, const char *path)
283
347
  break;
284
348
  }
285
349
 
286
- return at_pos;
350
+ return (int)at_pos;
287
351
  }
288
352
 
289
- unsigned int git_tree_entrycount(const git_tree *tree)
353
+ size_t git_tree_entrycount(const git_tree *tree)
290
354
  {
291
355
  assert(tree);
292
- return (unsigned int)tree->entries.length;
356
+ return tree->entries.length;
293
357
  }
294
358
 
295
- static int tree_error(const char *str)
359
+ unsigned int git_treebuilder_entrycount(git_treebuilder *bld)
296
360
  {
297
- giterr_set(GITERR_TREE, "%s", str);
361
+ assert(bld);
362
+ return (unsigned int)bld->entrycount;
363
+ }
364
+
365
+ static int tree_error(const char *str, const char *path)
366
+ {
367
+ if (path)
368
+ giterr_set(GITERR_TREE, "%s - %s", str, path);
369
+ else
370
+ giterr_set(GITERR_TREE, "%s", str);
298
371
  return -1;
299
372
  }
300
373
 
@@ -307,23 +380,26 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
307
380
  git_tree_entry *entry;
308
381
  int attr;
309
382
 
310
- if (git__strtol32(&attr, buffer, &buffer, 8) < 0 ||
311
- !buffer || !valid_filemode(attr))
312
- return tree_error("Failed to parse tree. Can't parse filemode");
383
+ if (git__strtol32(&attr, buffer, &buffer, 8) < 0 || !buffer)
384
+ return tree_error("Failed to parse tree. Can't parse filemode", NULL);
385
+
386
+ attr = normalize_filemode(attr); /* make sure to normalize the filemode */
313
387
 
314
388
  if (*buffer++ != ' ')
315
- return tree_error("Failed to parse tree. Object is corrupted");
389
+ return tree_error("Failed to parse tree. Object is corrupted", NULL);
316
390
 
317
391
  if (memchr(buffer, 0, buffer_end - buffer) == NULL)
318
- return tree_error("Failed to parse tree. Object is corrupted");
392
+ return tree_error("Failed to parse tree. Object is corrupted", NULL);
319
393
 
320
394
  /** Allocate the entry and store it in the entries vector */
321
395
  {
322
396
  entry = alloc_entry(buffer);
323
397
  GITERR_CHECK_ALLOC(entry);
324
398
 
325
- if (git_vector_insert(&tree->entries, entry) < 0)
399
+ if (git_vector_insert(&tree->entries, entry) < 0) {
400
+ git__free(entry);
326
401
  return -1;
402
+ }
327
403
 
328
404
  entry->attr = attr;
329
405
  }
@@ -346,14 +422,13 @@ int git_tree__parse(git_tree *tree, git_odb_object *obj)
346
422
  return tree_parse_buffer(tree, (char *)obj->raw.data, (char *)obj->raw.data + obj->raw.len);
347
423
  }
348
424
 
349
- static unsigned int find_next_dir(const char *dirname, git_index *index, unsigned int start)
425
+ static size_t find_next_dir(const char *dirname, git_index *index, size_t start)
350
426
  {
351
- unsigned int i, entries = git_index_entrycount(index);
352
- size_t dirlen;
427
+ size_t dirlen, i, entries = git_index_entrycount(index);
353
428
 
354
429
  dirlen = strlen(dirname);
355
430
  for (i = start; i < entries; ++i) {
356
- git_index_entry *entry = git_index_get(index, i);
431
+ const git_index_entry *entry = git_index_get_byindex(index, i);
357
432
  if (strlen(entry->path) < dirlen ||
358
433
  memcmp(entry->path, dirname, dirlen) ||
359
434
  (dirlen > 0 && entry->path[dirlen] != '/')) {
@@ -372,15 +447,21 @@ static int append_entry(
372
447
  {
373
448
  git_tree_entry *entry;
374
449
 
450
+ if (!valid_entry_name(filename))
451
+ return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
452
+
375
453
  entry = alloc_entry(filename);
376
454
  GITERR_CHECK_ALLOC(entry);
377
455
 
378
456
  git_oid_cpy(&entry->oid, id);
379
457
  entry->attr = (uint16_t)filemode;
380
458
 
381
- if (git_vector_insert(&bld->entries, entry) < 0)
459
+ if (git_vector_insert(&bld->entries, entry) < 0) {
460
+ git__free(entry);
382
461
  return -1;
462
+ }
383
463
 
464
+ bld->entrycount++;
384
465
  return 0;
385
466
  }
386
467
 
@@ -389,11 +470,10 @@ static int write_tree(
389
470
  git_repository *repo,
390
471
  git_index *index,
391
472
  const char *dirname,
392
- unsigned int start)
473
+ size_t start)
393
474
  {
394
475
  git_treebuilder *bld = NULL;
395
-
396
- unsigned int i, entries = git_index_entrycount(index);
476
+ size_t i, entries = git_index_entrycount(index);
397
477
  int error;
398
478
  size_t dirname_len = strlen(dirname);
399
479
  const git_tree_cache *cache;
@@ -401,13 +481,11 @@ static int write_tree(
401
481
  cache = git_tree_cache_get(index->tree, dirname);
402
482
  if (cache != NULL && cache->entries >= 0){
403
483
  git_oid_cpy(oid, &cache->oid);
404
- return find_next_dir(dirname, index, start);
484
+ return (int)find_next_dir(dirname, index, start);
405
485
  }
406
486
 
407
- error = git_treebuilder_create(&bld, NULL);
408
- if (bld == NULL) {
487
+ if ((error = git_treebuilder_create(&bld, NULL)) < 0 || bld == NULL)
409
488
  return -1;
410
- }
411
489
 
412
490
  /*
413
491
  * This loop is unfortunate, but necessary. The index doesn't have
@@ -415,8 +493,8 @@ static int write_tree(
415
493
  * need to keep track of the current position.
416
494
  */
417
495
  for (i = start; i < entries; ++i) {
418
- git_index_entry *entry = git_index_get(index, i);
419
- char *filename, *next_slash;
496
+ const git_index_entry *entry = git_index_get_byindex(index, i);
497
+ const char *filename, *next_slash;
420
498
 
421
499
  /*
422
500
  * If we've left our (sub)tree, exit the loop and return. The
@@ -447,7 +525,8 @@ static int write_tree(
447
525
  /* Write out the subtree */
448
526
  written = write_tree(&sub_oid, repo, index, subdir, i);
449
527
  if (written < 0) {
450
- tree_error("Failed to write subtree");
528
+ tree_error("Failed to write subtree", subdir);
529
+ git__free(subdir);
451
530
  goto on_error;
452
531
  } else {
453
532
  i = written - 1; /* -1 because of the loop increment */
@@ -465,18 +544,15 @@ static int write_tree(
465
544
  } else {
466
545
  last_comp = subdir;
467
546
  }
547
+
468
548
  error = append_entry(bld, last_comp, &sub_oid, S_IFDIR);
469
549
  git__free(subdir);
470
- if (error < 0) {
471
- tree_error("Failed to insert dir");
550
+ if (error < 0)
472
551
  goto on_error;
473
- }
474
552
  } else {
475
553
  error = append_entry(bld, filename, &entry->oid, entry->mode);
476
- if (error < 0) {
477
- tree_error("Failed to insert file");
554
+ if (error < 0)
478
555
  goto on_error;
479
- }
480
556
  }
481
557
  }
482
558
 
@@ -484,50 +560,48 @@ static int write_tree(
484
560
  goto on_error;
485
561
 
486
562
  git_treebuilder_free(bld);
487
- return i;
563
+ return (int)i;
488
564
 
489
565
  on_error:
490
566
  git_treebuilder_free(bld);
491
567
  return -1;
492
568
  }
493
569
 
494
- int git_tree_create_fromindex(git_oid *oid, git_index *index)
570
+ int git_tree__write_index(
571
+ git_oid *oid, git_index *index, git_repository *repo)
495
572
  {
496
573
  int ret;
497
- git_repository *repo;
574
+ bool old_ignore_case = false;
498
575
 
499
- repo = (git_repository *)GIT_REFCOUNT_OWNER(index);
576
+ assert(oid && index && repo);
500
577
 
501
- if (repo == NULL)
502
- return tree_error("Failed to create tree. "
503
- "The index file is not backed up by an existing repository");
578
+ if (git_index_has_conflicts(index)) {
579
+ giterr_set(GITERR_INDEX,
580
+ "Cannot create a tree from a not fully merged index.");
581
+ return GIT_EUNMERGED;
582
+ }
504
583
 
505
584
  if (index->tree != NULL && index->tree->entries >= 0) {
506
585
  git_oid_cpy(oid, &index->tree->oid);
507
586
  return 0;
508
587
  }
509
588
 
510
- /* The tree cache didn't help us */
511
- ret = write_tree(oid, repo, index, "", 0);
512
- return ret < 0 ? ret : 0;
513
- }
589
+ /* The tree cache didn't help us; we'll have to write
590
+ * out a tree. If the index is ignore_case, we must
591
+ * make it case-sensitive for the duration of the tree-write
592
+ * operation. */
514
593
 
515
- static void sort_entries(git_treebuilder *bld)
516
- {
517
- git_vector_sort(&bld->entries);
518
- }
594
+ if (index->ignore_case) {
595
+ old_ignore_case = true;
596
+ git_index__set_ignore_case(index, false);
597
+ }
519
598
 
520
- GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
521
- {
522
- /* 100664 mode is an early design mistake. Tree entries may bear
523
- * this mode in some old git repositories, but it's now deprecated.
524
- * We silently normalize while inserting new entries in a tree
525
- * being built.
526
- */
527
- if (filemode == GIT_FILEMODE_BLOB_GROUP_WRITABLE)
528
- return GIT_FILEMODE_BLOB;
599
+ ret = write_tree(oid, repo, index, "", 0);
529
600
 
530
- return filemode;
601
+ if (old_ignore_case)
602
+ git_index__set_ignore_case(index, true);
603
+
604
+ return ret < 0 ? ret : 0;
531
605
  }
532
606
 
533
607
  int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
@@ -547,13 +621,13 @@ int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
547
621
  goto on_error;
548
622
 
549
623
  if (source != NULL) {
550
- for (i = 0; i < source->entries.length; ++i) {
551
- git_tree_entry *entry_src = source->entries.contents[i];
624
+ git_tree_entry *entry_src;
552
625
 
626
+ git_vector_foreach(&source->entries, i, entry_src) {
553
627
  if (append_entry(
554
628
  bld, entry_src->filename,
555
629
  &entry_src->oid,
556
- normalize_filemode((git_filemode_t)entry_src->attr)) < 0)
630
+ entry_src->attr) < 0)
557
631
  goto on_error;
558
632
  }
559
633
  }
@@ -574,53 +648,51 @@ int git_treebuilder_insert(
574
648
  git_filemode_t filemode)
575
649
  {
576
650
  git_tree_entry *entry;
577
- int pos;
651
+ size_t pos;
578
652
 
579
653
  assert(bld && id && filename);
580
654
 
581
655
  if (!valid_filemode(filemode))
582
- return tree_error("Failed to insert entry. Invalid filemode");
583
-
584
- filemode = normalize_filemode(filemode);
656
+ return tree_error("Failed to insert entry. Invalid filemode for file", filename);
585
657
 
586
658
  if (!valid_entry_name(filename))
587
- return tree_error("Failed to insert entry. Invalid name for a tree entry");
588
-
589
- pos = tree_key_search(&bld->entries, filename, strlen(filename));
659
+ return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
590
660
 
591
- if (pos >= 0) {
661
+ if (!tree_key_search(&pos, &bld->entries, filename, strlen(filename))) {
592
662
  entry = git_vector_get(&bld->entries, pos);
593
- if (entry->removed)
663
+ if (entry->removed) {
594
664
  entry->removed = 0;
665
+ bld->entrycount++;
666
+ }
595
667
  } else {
596
668
  entry = alloc_entry(filename);
597
669
  GITERR_CHECK_ALLOC(entry);
670
+
671
+ if (git_vector_insert(&bld->entries, entry) < 0) {
672
+ git__free(entry);
673
+ return -1;
674
+ }
675
+
676
+ bld->entrycount++;
598
677
  }
599
678
 
600
679
  git_oid_cpy(&entry->oid, id);
601
680
  entry->attr = filemode;
602
681
 
603
- if (pos < 0) {
604
- if (git_vector_insert(&bld->entries, entry) < 0)
605
- return -1;
606
- }
607
-
608
- if (entry_out != NULL) {
682
+ if (entry_out)
609
683
  *entry_out = entry;
610
- }
611
684
 
612
685
  return 0;
613
686
  }
614
687
 
615
688
  static git_tree_entry *treebuilder_get(git_treebuilder *bld, const char *filename)
616
689
  {
617
- int idx;
690
+ size_t idx;
618
691
  git_tree_entry *entry;
619
692
 
620
693
  assert(bld && filename);
621
694
 
622
- idx = tree_key_search(&bld->entries, filename, strlen(filename));
623
- if (idx < 0)
695
+ if (tree_key_search(&idx, &bld->entries, filename, strlen(filename)) < 0)
624
696
  return NULL;
625
697
 
626
698
  entry = git_vector_get(&bld->entries, idx);
@@ -640,27 +712,29 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
640
712
  git_tree_entry *remove_ptr = treebuilder_get(bld, filename);
641
713
 
642
714
  if (remove_ptr == NULL || remove_ptr->removed)
643
- return tree_error("Failed to remove entry. File isn't in the tree");
715
+ return tree_error("Failed to remove entry. File isn't in the tree", filename);
644
716
 
645
717
  remove_ptr->removed = 1;
718
+ bld->entrycount--;
646
719
  return 0;
647
720
  }
648
721
 
649
722
  int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld)
650
723
  {
651
- unsigned int i;
724
+ int error = 0;
725
+ size_t i;
652
726
  git_buf tree = GIT_BUF_INIT;
653
727
  git_odb *odb;
654
728
 
655
729
  assert(bld);
656
730
 
657
- sort_entries(bld);
731
+ git_vector_sort(&bld->entries);
658
732
 
659
733
  /* Grow the buffer beforehand to an estimated size */
660
- git_buf_grow(&tree, bld->entries.length * 72);
734
+ error = git_buf_grow(&tree, bld->entries.length * 72);
661
735
 
662
- for (i = 0; i < bld->entries.length; ++i) {
663
- git_tree_entry *entry = bld->entries.contents[i];
736
+ for (i = 0; i < bld->entries.length && !error; ++i) {
737
+ git_tree_entry *entry = git_vector_get(&bld->entries, i);
664
738
 
665
739
  if (entry->removed)
666
740
  continue;
@@ -668,50 +742,49 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
668
742
  git_buf_printf(&tree, "%o ", entry->attr);
669
743
  git_buf_put(&tree, entry->filename, entry->filename_len + 1);
670
744
  git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ);
671
- }
672
-
673
- if (git_buf_oom(&tree))
674
- goto on_error;
675
745
 
676
- if (git_repository_odb__weakptr(&odb, repo) < 0)
677
- goto on_error;
678
-
679
-
680
- if (git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE) < 0)
681
- goto on_error;
746
+ if (git_buf_oom(&tree))
747
+ error = -1;
748
+ }
682
749
 
683
- git_buf_free(&tree);
684
- return 0;
750
+ if (!error &&
751
+ !(error = git_repository_odb__weakptr(&odb, repo)))
752
+ error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
685
753
 
686
- on_error:
687
754
  git_buf_free(&tree);
688
- return -1;
755
+ return error;
689
756
  }
690
757
 
691
- void git_treebuilder_filter(git_treebuilder *bld, int (*filter)(const git_tree_entry *, void *), void *payload)
758
+ void git_treebuilder_filter(
759
+ git_treebuilder *bld,
760
+ git_treebuilder_filter_cb filter,
761
+ void *payload)
692
762
  {
693
- unsigned int i;
763
+ size_t i;
764
+ git_tree_entry *entry;
694
765
 
695
766
  assert(bld && filter);
696
767
 
697
- for (i = 0; i < bld->entries.length; ++i) {
698
- git_tree_entry *entry = bld->entries.contents[i];
699
- if (!entry->removed && filter(entry, payload))
768
+ git_vector_foreach(&bld->entries, i, entry) {
769
+ if (!entry->removed && filter(entry, payload)) {
700
770
  entry->removed = 1;
771
+ bld->entrycount--;
772
+ }
701
773
  }
702
774
  }
703
775
 
704
776
  void git_treebuilder_clear(git_treebuilder *bld)
705
777
  {
706
- unsigned int i;
778
+ size_t i;
779
+ git_tree_entry *e;
780
+
707
781
  assert(bld);
708
782
 
709
- for (i = 0; i < bld->entries.length; ++i) {
710
- git_tree_entry *e = bld->entries.contents[i];
783
+ git_vector_foreach(&bld->entries, i, e)
711
784
  git_tree_entry_free(e);
712
- }
713
785
 
714
786
  git_vector_clear(&bld->entries);
787
+ bld->entrycount = 0;
715
788
  }
716
789
 
717
790
  void git_treebuilder_free(git_treebuilder *bld)
@@ -797,24 +870,25 @@ int git_tree_entry_bypath(
797
870
  }
798
871
 
799
872
  static int tree_walk(
800
- git_tree *tree,
873
+ const git_tree *tree,
801
874
  git_treewalk_cb callback,
802
875
  git_buf *path,
803
876
  void *payload,
804
877
  bool preorder)
805
878
  {
806
879
  int error = 0;
807
- unsigned int i;
808
-
809
- for (i = 0; i < tree->entries.length; ++i) {
810
- git_tree_entry *entry = tree->entries.contents[i];
880
+ size_t i;
881
+ const git_tree_entry *entry;
811
882
 
883
+ git_vector_foreach(&tree->entries, i, entry) {
812
884
  if (preorder) {
813
885
  error = callback(path->ptr, entry, payload);
814
886
  if (error > 0)
815
887
  continue;
816
- if (error < 0)
888
+ if (error < 0) {
889
+ giterr_clear();
817
890
  return GIT_EUSER;
891
+ }
818
892
  }
819
893
 
820
894
  if (git_tree_entry__is_tree(entry)) {
@@ -841,6 +915,7 @@ static int tree_walk(
841
915
  }
842
916
 
843
917
  if (!preorder && callback(path->ptr, entry, payload) < 0) {
918
+ giterr_clear();
844
919
  error = GIT_EUSER;
845
920
  break;
846
921
  }
@@ -849,25 +924,23 @@ static int tree_walk(
849
924
  return error;
850
925
  }
851
926
 
852
- int git_tree_walk(git_tree *tree, git_treewalk_cb callback, int mode, void *payload)
927
+ int git_tree_walk(
928
+ const git_tree *tree,
929
+ git_treewalk_mode mode,
930
+ git_treewalk_cb callback,
931
+ void *payload)
853
932
  {
854
933
  int error = 0;
855
934
  git_buf root_path = GIT_BUF_INIT;
856
935
 
857
- switch (mode) {
858
- case GIT_TREEWALK_POST:
859
- error = tree_walk(tree, callback, &root_path, payload, false);
860
- break;
861
-
862
- case GIT_TREEWALK_PRE:
863
- error = tree_walk(tree, callback, &root_path, payload, true);
864
- break;
865
-
866
- default:
867
- giterr_set(GITERR_INVALID, "Invalid walking mode for tree walk");
868
- return -1;
936
+ if (mode != GIT_TREEWALK_POST && mode != GIT_TREEWALK_PRE) {
937
+ giterr_set(GITERR_INVALID, "Invalid walking mode for tree walk");
938
+ return -1;
869
939
  }
870
940
 
941
+ error = tree_walk(
942
+ tree, callback, &root_path, payload, (mode == GIT_TREEWALK_PRE));
943
+
871
944
  git_buf_free(&root_path);
872
945
 
873
946
  return error;