rugged 0.17.0.b7 → 0.18.0.b1

Sign up to get free protection for your applications and to get access to all the features.
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;