rugged 0.18.0.gh.de28323 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (283) hide show
  1. data/README.md +9 -4
  2. data/Rakefile +1 -1
  3. data/ext/rugged/extconf.rb +10 -0
  4. data/ext/rugged/rugged.c +153 -86
  5. data/ext/rugged/rugged.h +44 -33
  6. data/ext/rugged/rugged_blob.c +288 -60
  7. data/ext/rugged/rugged_branch.c +82 -57
  8. data/ext/rugged/rugged_commit.c +83 -86
  9. data/ext/rugged/rugged_config.c +68 -68
  10. data/ext/rugged/rugged_diff.c +509 -0
  11. data/ext/rugged/rugged_diff_delta.c +94 -0
  12. data/ext/rugged/rugged_diff_hunk.c +100 -0
  13. data/ext/rugged/rugged_diff_line.c +79 -0
  14. data/ext/rugged/rugged_diff_patch.c +169 -0
  15. data/ext/rugged/rugged_index.c +539 -8
  16. data/ext/rugged/rugged_note.c +74 -80
  17. data/ext/rugged/rugged_object.c +63 -8
  18. data/ext/rugged/rugged_reference.c +231 -145
  19. data/ext/rugged/rugged_remote.c +509 -53
  20. data/ext/rugged/rugged_repo.c +572 -236
  21. data/ext/rugged/rugged_revwalk.c +59 -36
  22. data/ext/rugged/rugged_settings.c +7 -9
  23. data/ext/rugged/rugged_signature.c +7 -11
  24. data/ext/rugged/rugged_tag.c +93 -39
  25. data/ext/rugged/rugged_tree.c +321 -58
  26. data/lib/rugged.rb +1 -0
  27. data/lib/rugged/commit.rb +16 -1
  28. data/lib/rugged/console.rb +9 -0
  29. data/lib/rugged/diff.rb +19 -0
  30. data/lib/rugged/diff/delta.rb +54 -0
  31. data/lib/rugged/diff/hunk.rb +23 -0
  32. data/lib/rugged/diff/line.rb +29 -0
  33. data/lib/rugged/diff/patch.rb +28 -0
  34. data/lib/rugged/repository.rb +36 -39
  35. data/lib/rugged/version.rb +1 -1
  36. data/test/blob_test.rb +308 -1
  37. data/test/branch_test.rb +7 -0
  38. data/test/commit_test.rb +7 -10
  39. data/test/coverage/cover.rb +9 -1
  40. data/test/diff_test.rb +777 -0
  41. data/test/fixtures/archive.tar.gz +0 -0
  42. data/test/fixtures/attr/attr0 +1 -0
  43. data/test/fixtures/attr/attr1 +29 -0
  44. data/test/fixtures/attr/attr2 +21 -0
  45. data/test/fixtures/attr/attr3 +4 -0
  46. data/test/fixtures/attr/binfile +1 -0
  47. data/test/fixtures/attr/dir/file +0 -0
  48. data/test/fixtures/attr/file +1 -0
  49. data/test/fixtures/attr/gitattributes +29 -0
  50. data/test/fixtures/attr/gitignore +2 -0
  51. data/test/fixtures/attr/ign +1 -0
  52. data/test/fixtures/attr/macro_bad +1 -0
  53. data/test/fixtures/attr/macro_test +1 -0
  54. data/test/fixtures/attr/root_test1 +1 -0
  55. data/test/fixtures/attr/root_test2 +6 -0
  56. data/test/fixtures/attr/root_test3 +19 -0
  57. data/test/fixtures/attr/root_test4.txt +14 -0
  58. data/test/fixtures/attr/sub/abc +37 -0
  59. data/test/fixtures/attr/sub/dir/file +0 -0
  60. data/test/fixtures/attr/sub/file +1 -0
  61. data/test/fixtures/attr/sub/ign/file +1 -0
  62. data/test/fixtures/attr/sub/ign/sub/file +1 -0
  63. data/test/fixtures/attr/sub/sub/dir +0 -0
  64. data/test/fixtures/attr/sub/sub/file +1 -0
  65. data/test/fixtures/attr/sub/sub/subsub.txt +1 -0
  66. data/test/fixtures/attr/sub/subdir_test1 +2 -0
  67. data/test/fixtures/attr/sub/subdir_test2.txt +1 -0
  68. data/test/fixtures/diff/another.txt +38 -0
  69. data/test/fixtures/diff/readme.txt +36 -0
  70. data/test/fixtures/mergedrepo/conflicts-one.txt +5 -0
  71. data/test/fixtures/mergedrepo/conflicts-two.txt +5 -0
  72. data/test/fixtures/mergedrepo/one.txt +10 -0
  73. data/test/fixtures/mergedrepo/two.txt +12 -0
  74. data/test/fixtures/status/current_file +1 -0
  75. data/test/fixtures/status/ignored_file +1 -0
  76. data/test/fixtures/status/modified_file +2 -0
  77. data/test/fixtures/status/new_file +1 -0
  78. data/test/fixtures/status/staged_changes +2 -0
  79. data/test/fixtures/status/staged_changes_modified_file +3 -0
  80. data/test/fixtures/status/staged_delete_modified_file +1 -0
  81. data/test/fixtures/status/staged_new_file +1 -0
  82. data/test/fixtures/status/staged_new_file_modified_file +2 -0
  83. data/test/fixtures/status/subdir.txt +2 -0
  84. data/test/fixtures/status/subdir/current_file +1 -0
  85. data/test/fixtures/status/subdir/modified_file +2 -0
  86. data/test/fixtures/status/subdir/new_file +1 -0
  87. data/test/fixtures/status//350/277/231 +1 -0
  88. data/test/fixtures/testrepo.git/config +5 -0
  89. data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
  90. data/test/fixtures/text_file.md +464 -0
  91. data/test/fixtures/unsymlinked.git/HEAD +1 -0
  92. data/test/fixtures/unsymlinked.git/config +6 -0
  93. data/test/fixtures/unsymlinked.git/description +1 -0
  94. data/test/fixtures/unsymlinked.git/info/exclude +2 -0
  95. data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
  96. data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
  97. data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
  98. data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
  99. data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
  100. data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
  101. data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
  102. data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
  103. data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
  104. data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +2 -0
  105. data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
  106. data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
  107. data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
  108. data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
  109. data/test/fixtures/unsymlinked.git/refs/heads/exe-file +1 -0
  110. data/test/fixtures/unsymlinked.git/refs/heads/master +1 -0
  111. data/test/fixtures/unsymlinked.git/refs/heads/reg-file +1 -0
  112. data/test/index_test.rb +120 -0
  113. data/test/reference_test.rb +38 -3
  114. data/test/remote_test.rb +224 -3
  115. data/test/repo_reset_test.rb +2 -0
  116. data/test/repo_test.rb +147 -10
  117. data/test/test_helper.rb +5 -2
  118. data/vendor/libgit2/include/git2/attr.h +3 -3
  119. data/vendor/libgit2/include/git2/blob.h +11 -17
  120. data/vendor/libgit2/include/git2/branch.h +3 -2
  121. data/vendor/libgit2/include/git2/checkout.h +7 -0
  122. data/vendor/libgit2/include/git2/clone.h +3 -0
  123. data/vendor/libgit2/include/git2/commit.h +61 -66
  124. data/vendor/libgit2/include/git2/common.h +73 -42
  125. data/vendor/libgit2/include/git2/config.h +57 -71
  126. data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
  127. data/vendor/libgit2/include/git2/diff.h +179 -30
  128. data/vendor/libgit2/include/git2/errors.h +3 -3
  129. data/vendor/libgit2/include/git2/index.h +225 -146
  130. data/vendor/libgit2/include/git2/indexer.h +2 -22
  131. data/vendor/libgit2/include/git2/inttypes.h +9 -9
  132. data/vendor/libgit2/include/git2/merge.h +123 -5
  133. data/vendor/libgit2/include/git2/odb.h +59 -38
  134. data/vendor/libgit2/include/git2/odb_backend.h +45 -104
  135. data/vendor/libgit2/include/git2/oid.h +30 -19
  136. data/vendor/libgit2/include/git2/pack.h +21 -3
  137. data/vendor/libgit2/include/git2/refdb.h +0 -35
  138. data/vendor/libgit2/include/git2/refs.h +93 -31
  139. data/vendor/libgit2/include/git2/refspec.h +17 -0
  140. data/vendor/libgit2/include/git2/remote.h +60 -20
  141. data/vendor/libgit2/include/git2/repository.h +48 -70
  142. data/vendor/libgit2/include/git2/reset.h +3 -3
  143. data/vendor/libgit2/include/git2/revparse.h +22 -0
  144. data/vendor/libgit2/include/git2/stash.h +1 -1
  145. data/vendor/libgit2/include/git2/status.h +131 -56
  146. data/vendor/libgit2/include/git2/strarray.h +2 -2
  147. data/vendor/libgit2/include/git2/submodule.h +16 -16
  148. data/vendor/libgit2/include/git2/sys/commit.h +46 -0
  149. data/vendor/libgit2/include/git2/sys/config.h +71 -0
  150. data/vendor/libgit2/include/git2/sys/index.h +179 -0
  151. data/vendor/libgit2/include/git2/sys/odb_backend.h +86 -0
  152. data/vendor/libgit2/include/git2/sys/refdb_backend.h +158 -0
  153. data/vendor/libgit2/include/git2/sys/refs.h +38 -0
  154. data/vendor/libgit2/include/git2/sys/repository.h +106 -0
  155. data/vendor/libgit2/include/git2/tag.h +44 -18
  156. data/vendor/libgit2/include/git2/trace.h +1 -2
  157. data/vendor/libgit2/include/git2/transport.h +74 -0
  158. data/vendor/libgit2/include/git2/tree.h +12 -22
  159. data/vendor/libgit2/include/git2/types.h +33 -0
  160. data/vendor/libgit2/include/git2/version.h +2 -2
  161. data/vendor/libgit2/src/array.h +66 -0
  162. data/vendor/libgit2/src/attr.c +26 -13
  163. data/vendor/libgit2/src/attr_file.c +3 -2
  164. data/vendor/libgit2/src/attr_file.h +3 -3
  165. data/vendor/libgit2/src/attrcache.h +4 -4
  166. data/vendor/libgit2/src/blob.c +13 -9
  167. data/vendor/libgit2/src/blob.h +2 -2
  168. data/vendor/libgit2/src/branch.c +67 -49
  169. data/vendor/libgit2/src/cache.c +224 -54
  170. data/vendor/libgit2/src/cache.h +33 -20
  171. data/vendor/libgit2/src/checkout.c +145 -85
  172. data/vendor/libgit2/src/clone.c +62 -50
  173. data/vendor/libgit2/src/commit.c +74 -40
  174. data/vendor/libgit2/src/commit.h +2 -3
  175. data/vendor/libgit2/src/commit_list.c +14 -8
  176. data/vendor/libgit2/src/config.c +119 -36
  177. data/vendor/libgit2/src/config.h +3 -0
  178. data/vendor/libgit2/src/config_cache.c +24 -7
  179. data/vendor/libgit2/src/config_file.c +9 -6
  180. data/vendor/libgit2/src/crlf.c +4 -2
  181. data/vendor/libgit2/src/date.c +3 -3
  182. data/vendor/libgit2/src/delta.c +1 -1
  183. data/vendor/libgit2/src/diff.c +681 -303
  184. data/vendor/libgit2/src/diff.h +34 -2
  185. data/vendor/libgit2/src/diff_driver.c +405 -0
  186. data/vendor/libgit2/src/diff_driver.h +49 -0
  187. data/vendor/libgit2/src/diff_file.c +447 -0
  188. data/vendor/libgit2/src/diff_file.h +58 -0
  189. data/vendor/libgit2/src/diff_patch.c +995 -0
  190. data/vendor/libgit2/src/diff_patch.h +46 -0
  191. data/vendor/libgit2/src/diff_print.c +430 -0
  192. data/vendor/libgit2/src/diff_tform.c +464 -203
  193. data/vendor/libgit2/src/diff_xdiff.c +166 -0
  194. data/vendor/libgit2/src/diff_xdiff.h +28 -0
  195. data/vendor/libgit2/src/fetch.c +11 -4
  196. data/vendor/libgit2/src/fileops.c +85 -61
  197. data/vendor/libgit2/src/fileops.h +4 -0
  198. data/vendor/libgit2/src/global.c +10 -2
  199. data/vendor/libgit2/src/global.h +0 -8
  200. data/vendor/libgit2/src/hash/hash_generic.h +3 -3
  201. data/vendor/libgit2/src/hash/hash_win32.h +4 -4
  202. data/vendor/libgit2/src/hashsig.c +0 -1
  203. data/vendor/libgit2/src/ignore.c +68 -28
  204. data/vendor/libgit2/src/ignore.h +10 -1
  205. data/vendor/libgit2/src/index.c +666 -84
  206. data/vendor/libgit2/src/index.h +6 -0
  207. data/vendor/libgit2/src/indexer.c +10 -28
  208. data/vendor/libgit2/src/iterator.c +427 -283
  209. data/vendor/libgit2/src/iterator.h +58 -4
  210. data/vendor/libgit2/src/merge.c +1892 -32
  211. data/vendor/libgit2/src/merge.h +132 -5
  212. data/vendor/libgit2/src/merge_file.c +174 -0
  213. data/vendor/libgit2/src/merge_file.h +71 -0
  214. data/vendor/libgit2/src/mwindow.c +1 -1
  215. data/vendor/libgit2/src/notes.c +45 -48
  216. data/vendor/libgit2/src/object.c +89 -127
  217. data/vendor/libgit2/src/object.h +0 -1
  218. data/vendor/libgit2/src/object_api.c +129 -0
  219. data/vendor/libgit2/src/odb.c +156 -59
  220. data/vendor/libgit2/src/odb.h +5 -2
  221. data/vendor/libgit2/src/odb_loose.c +31 -17
  222. data/vendor/libgit2/src/odb_pack.c +39 -43
  223. data/vendor/libgit2/src/oid.c +62 -27
  224. data/vendor/libgit2/src/oid.h +33 -0
  225. data/vendor/libgit2/src/oidmap.h +4 -6
  226. data/vendor/libgit2/src/pack-objects.c +54 -22
  227. data/vendor/libgit2/src/pack.c +98 -56
  228. data/vendor/libgit2/src/pack.h +3 -1
  229. data/vendor/libgit2/src/pathspec.c +26 -1
  230. data/vendor/libgit2/src/pathspec.h +14 -0
  231. data/vendor/libgit2/src/pool.c +5 -0
  232. data/vendor/libgit2/src/posix.c +2 -2
  233. data/vendor/libgit2/src/posix.h +3 -0
  234. data/vendor/libgit2/src/push.c +13 -10
  235. data/vendor/libgit2/src/refdb.c +82 -62
  236. data/vendor/libgit2/src/refdb.h +16 -16
  237. data/vendor/libgit2/src/refdb_fs.c +386 -133
  238. data/vendor/libgit2/src/reflog.c +3 -1
  239. data/vendor/libgit2/src/refs.c +247 -221
  240. data/vendor/libgit2/src/refs.h +2 -1
  241. data/vendor/libgit2/src/refspec.c +18 -1
  242. data/vendor/libgit2/src/refspec.h +3 -1
  243. data/vendor/libgit2/src/remote.c +434 -253
  244. data/vendor/libgit2/src/remote.h +5 -3
  245. data/vendor/libgit2/src/repository.c +197 -111
  246. data/vendor/libgit2/src/repository.h +26 -5
  247. data/vendor/libgit2/src/reset.c +1 -1
  248. data/vendor/libgit2/src/revparse.c +84 -79
  249. data/vendor/libgit2/src/revwalk.c +1 -1
  250. data/vendor/libgit2/src/signature.c +22 -10
  251. data/vendor/libgit2/src/stash.c +5 -2
  252. data/vendor/libgit2/src/status.c +311 -107
  253. data/vendor/libgit2/src/status.h +23 -0
  254. data/vendor/libgit2/src/submodule.c +21 -13
  255. data/vendor/libgit2/src/tag.c +42 -31
  256. data/vendor/libgit2/src/tag.h +2 -3
  257. data/vendor/libgit2/src/thread-utils.h +105 -3
  258. data/vendor/libgit2/src/trace.c +1 -2
  259. data/vendor/libgit2/src/trace.h +3 -3
  260. data/vendor/libgit2/src/transport.c +18 -6
  261. data/vendor/libgit2/src/transports/cred.c +103 -1
  262. data/vendor/libgit2/src/transports/local.c +19 -9
  263. data/vendor/libgit2/src/transports/smart_protocol.c +32 -12
  264. data/vendor/libgit2/src/transports/ssh.c +519 -0
  265. data/vendor/libgit2/src/transports/winhttp.c +3 -1
  266. data/vendor/libgit2/src/tree.c +26 -28
  267. data/vendor/libgit2/src/tree.h +3 -3
  268. data/vendor/libgit2/src/unix/posix.h +2 -0
  269. data/vendor/libgit2/src/util.c +43 -6
  270. data/vendor/libgit2/src/util.h +40 -12
  271. data/vendor/libgit2/src/vector.c +3 -5
  272. data/vendor/libgit2/src/vector.h +9 -0
  273. data/vendor/libgit2/src/win32/dir.c +1 -1
  274. data/vendor/libgit2/src/win32/error.c +2 -0
  275. data/vendor/libgit2/src/win32/findfile.c +3 -6
  276. data/vendor/libgit2/src/win32/posix_w32.c +85 -59
  277. data/vendor/libgit2/src/win32/pthread.c +16 -8
  278. data/vendor/libgit2/src/win32/pthread.h +7 -4
  279. metadata +407 -306
  280. data/test/coverage/HEAD.json +0 -1
  281. data/vendor/libgit2/include/git2/refdb_backend.h +0 -109
  282. data/vendor/libgit2/src/diff_output.c +0 -1819
  283. data/vendor/libgit2/src/diff_output.h +0 -93
@@ -23,6 +23,7 @@
23
23
  */
24
24
 
25
25
  #include "rugged.h"
26
+ #include <git2/sys/repository.h>
26
27
 
27
28
  extern VALUE rb_mRugged;
28
29
  extern VALUE rb_eRuggedError;
@@ -30,18 +31,21 @@ extern VALUE rb_cRuggedIndex;
30
31
  extern VALUE rb_cRuggedConfig;
31
32
  extern VALUE rb_cRuggedBackend;
32
33
  extern VALUE rb_cRuggedRemote;
34
+ extern VALUE rb_cRuggedReference;
33
35
 
34
36
  VALUE rb_cRuggedRepo;
35
37
  VALUE rb_cRuggedOdbObject;
36
38
 
39
+ static ID id_call;
40
+
37
41
  /*
38
- * call-seq:
39
- * odb_obj.oid -> hex_oid
42
+ * call-seq:
43
+ * odb_obj.oid -> hex_oid
40
44
  *
41
- * Return the Object ID (a 40 character SHA1 hash) for this raw
42
- * object.
45
+ * Return the Object ID (a 40 character SHA1 hash) for this raw
46
+ * object.
43
47
  *
44
- * odb_obj.oid #=> "d8786bfc97485e8d7b19b21fb88c8ef1f199fc3f"
48
+ * odb_obj.oid #=> "d8786bfc97485e8d7b19b21fb88c8ef1f199fc3f"
45
49
  */
46
50
  static VALUE rb_git_odbobj_oid(VALUE self)
47
51
  {
@@ -51,31 +55,31 @@ static VALUE rb_git_odbobj_oid(VALUE self)
51
55
  }
52
56
 
53
57
  /*
54
- * call-seq:
55
- * odb_obj.data -> buffer
58
+ * call-seq:
59
+ * odb_obj.data -> buffer
56
60
  *
57
- * Return an ASCII buffer with the raw bytes that form the Git object.
61
+ * Return an ASCII buffer with the raw bytes that form the Git object.
58
62
  *
59
- * odb_obj.data #=> "tree 87ebee8367f9cc5ac04858b3bd5610ca74f04df9\n"
60
- * #=> "parent 68d041ee999cb07c6496fbdd4f384095de6ca9e1\n"
61
- * #=> "author Vicent Martí <tanoku@gmail.com> 1326863045 -0800\n"
62
- * #=> ...
63
+ * odb_obj.data #=> "tree 87ebee8367f9cc5ac04858b3bd5610ca74f04df9\n"
64
+ * #=> "parent 68d041ee999cb07c6496fbdd4f384095de6ca9e1\n"
65
+ * #=> "author Vicent Martí <tanoku@gmail.com> 1326863045 -0800\n"
66
+ * #=> ...
63
67
  */
64
68
  static VALUE rb_git_odbobj_data(VALUE self)
65
69
  {
66
70
  git_odb_object *obj;
67
71
  Data_Get_Struct(self, git_odb_object, obj);
68
- return rugged_str_ascii(git_odb_object_data(obj), git_odb_object_size(obj));
72
+ return rb_str_new(git_odb_object_data(obj), git_odb_object_size(obj));
69
73
  }
70
74
 
71
75
  /*
72
- * call-seq:
73
- * odb_obj.size -> size
76
+ * call-seq:
77
+ * odb_obj.size -> size
74
78
  *
75
- * Return the size in bytes of the Git object after decompression. This is
76
- * also the size of the +obj.data+ buffer.
79
+ * Return the size in bytes of the Git object after decompression. This is
80
+ * also the size of the +obj.data+ buffer.
77
81
  *
78
- * odb_obj.size #=> 231
82
+ * odb_obj.size #=> 231
79
83
  */
80
84
  static VALUE rb_git_odbobj_size(VALUE self)
81
85
  {
@@ -85,13 +89,13 @@ static VALUE rb_git_odbobj_size(VALUE self)
85
89
  }
86
90
 
87
91
  /*
88
- * call-seq:
89
- * odb_obj.type -> Symbol
92
+ * call-seq:
93
+ * odb_obj.type -> Symbol
90
94
  *
91
- * Return a Ruby symbol representing the basic Git type of this object.
92
- * Possible values are +:tree+, +:blob+, +:commit+ and +:tag+
95
+ * Return a Ruby symbol representing the basic Git type of this object.
96
+ * Possible values are +:tree+, +:blob+, +:commit+ and +:tag+.
93
97
  *
94
- * odb_obj.type #=> :tag
98
+ * odb_obj.type #=> :tag
95
99
  */
96
100
  static VALUE rb_git_odbobj_type(VALUE self)
97
101
  {
@@ -171,19 +175,21 @@ static void load_alternates(git_repository *repo, VALUE rb_alternates)
171
175
  rugged_exception_check(error);
172
176
  }
173
177
 
174
- static void set_repository_options(git_repository *repo, VALUE rb_options)
175
- {
176
- int error = 0;
177
-
178
- if (NIL_P(rb_options))
179
- return;
180
-
181
- Check_Type(rb_options, T_HASH);
182
-
183
- /* Check for `:alternates` */
184
- load_alternates(repo, rb_hash_aref(rb_options, CSTR2SYM("alternates")));
185
- }
186
-
178
+ /*
179
+ * call-seq:
180
+ * Repository.bare(path[, alternates]) -> repository
181
+ *
182
+ * Open a bare Git repository at +path+ and return a +Repository+
183
+ * object representing it.
184
+ *
185
+ * This is faster than Rugged::Repository.new, as it won't attempt to perform
186
+ * any +.git+ directory discovery, won't try to load the config options to
187
+ * determine whether the repository is bare and won't try to load the workdir.
188
+ *
189
+ * Optionally, you can pass a list of alternate object folders.
190
+ *
191
+ * Rugged::Repository.bare(path, ['./other/repo/.git/objects'])
192
+ */
187
193
  static VALUE rb_git_repo_open_bare(int argc, VALUE *argv, VALUE klass)
188
194
  {
189
195
  git_repository *repo;
@@ -202,25 +208,28 @@ static VALUE rb_git_repo_open_bare(int argc, VALUE *argv, VALUE klass)
202
208
  }
203
209
 
204
210
  /*
205
- * call-seq:
206
- * Rugged::Repository.new(path, options = {}) -> repository
211
+ * call-seq:
212
+ * Repository.new(path, options = {}) -> repository
207
213
  *
208
- * Open a Git repository in the given +path+ and return a +Repository+ object
209
- * representing it. An exception will be thrown if +path+ doesn't point to a
210
- * valid repository. If you need to create a repository from scratch, use
211
- * +Rugged::Repository.init+ instead.
214
+ * Open a Git repository in the given +path+ and return a +Repository+ object
215
+ * representing it. An exception will be thrown if +path+ doesn't point to a
216
+ * valid repository. If you need to create a repository from scratch, use
217
+ * Rugged::Repository.init instead.
212
218
  *
213
- * The +path+ must point to the actual folder (+.git+) of a Git repository.
214
- * If you're unsure of where is this located, use +Rugged::Repository.discover+
215
- * instead.
219
+ * The +path+ must point to either the actual folder (+.git+) of a Git repository,
220
+ * or to the directorly that contains the +.git+ folder.
216
221
  *
217
- * Rugged::Repository.new('~/test/.git') #=> #<Rugged::Repository:0x108849488>
222
+ * See also Rugged::Repository.discover and Rugged::Repository.bare.
218
223
  *
219
- * +options+ is an optional hash with the following keys:
224
+ * The following options can be passed in the +options+ Hash:
220
225
  *
221
- * - +:alternates+: +Array+ with a list of alternate object folders, e.g.
226
+ * :alternates ::
227
+ * A list of alternate object folders.
222
228
  *
223
- * Rugged::Repository.new(path, :alternates => ['./other/repo/.git/objects'])
229
+ * Examples:
230
+ *
231
+ * Rugged::Repository.new('~/test/.git') #=> #<Rugged::Repository:0x108849488>
232
+ * Rugged::Repository.new(path, :alternates => ['./other/repo/.git/objects'])
224
233
  */
225
234
  static VALUE rb_git_repo_new(int argc, VALUE *argv, VALUE klass)
226
235
  {
@@ -228,31 +237,35 @@ static VALUE rb_git_repo_new(int argc, VALUE *argv, VALUE klass)
228
237
  int error = 0;
229
238
  VALUE rb_path, rb_options;
230
239
 
231
- rb_scan_args(argc, argv, "11", &rb_path, &rb_options);
240
+ rb_scan_args(argc, argv, "10:", &rb_path, &rb_options);
232
241
  Check_Type(rb_path, T_STRING);
233
242
 
234
243
  error = git_repository_open(&repo, StringValueCStr(rb_path));
235
244
  rugged_exception_check(error);
236
- set_repository_options(repo, rb_options);
245
+
246
+ if (!NIL_P(rb_options)) {
247
+ /* Check for `:alternates` */
248
+ load_alternates(repo, rb_hash_aref(rb_options, CSTR2SYM("alternates")));
249
+ }
237
250
 
238
251
  return rugged_repo_new(klass, repo);
239
252
  }
240
253
 
241
254
  /*
242
- * call-seq:
243
- * init_at(path, is_bare = false) -> repository
255
+ * call-seq:
256
+ * Repository.init_at(path, is_bare = false) -> repository
244
257
  *
245
- * Initialize a Git repository in +path+. This implies creating all the
246
- * necessary files on the FS, or re-initializing an already existing
247
- * repository if the files have already been created.
258
+ * Initialize a Git repository in +path+. This implies creating all the
259
+ * necessary files on the FS, or re-initializing an already existing
260
+ * repository if the files have already been created.
248
261
  *
249
- * The +is_bare+ (optional, defaults to false) attribute specifies whether
250
- * the Repository should be created on disk as bare or not.
251
- * Bare repositories have no working directory and are created in the root
252
- * of +path+. Non-bare repositories are created in a +.git+ folder and
253
- * use +path+ as working directory.
262
+ * The +is_bare+ (optional, defaults to false) attribute specifies whether
263
+ * the Repository should be created on disk as bare or not.
264
+ * Bare repositories have no working directory and are created in the root
265
+ * of +path+. Non-bare repositories are created in a +.git+ folder and
266
+ * use +path+ as working directory.
254
267
  *
255
- * Rugged::Repository.init_at('~/repository', :bare) #=> #<Rugged::Repository:0x108849488>
268
+ * Rugged::Repository.init_at('~/repository', :bare) #=> #<Rugged::Repository:0x108849488>
256
269
  */
257
270
  static VALUE rb_git_repo_init_at(int argc, VALUE *argv, VALUE klass)
258
271
  {
@@ -272,6 +285,106 @@ static VALUE rb_git_repo_init_at(int argc, VALUE *argv, VALUE klass)
272
285
  return rugged_repo_new(klass, repo);
273
286
  }
274
287
 
288
+ struct clone_fetch_callback_payload
289
+ {
290
+ VALUE proc;
291
+ VALUE exception;
292
+ const git_transfer_progress *stats;
293
+ };
294
+
295
+ static VALUE clone_fetch_callback_inner(struct clone_fetch_callback_payload *fetch_payload)
296
+ {
297
+ rb_funcall(fetch_payload->proc, id_call, 4,
298
+ UINT2NUM(fetch_payload->stats->total_objects),
299
+ UINT2NUM(fetch_payload->stats->indexed_objects),
300
+ UINT2NUM(fetch_payload->stats->received_objects),
301
+ INT2FIX(fetch_payload->stats->received_bytes));
302
+ return GIT_OK;
303
+ }
304
+
305
+ static VALUE clone_fetch_callback_rescue(struct clone_fetch_callback_payload *fetch_payload, VALUE exception)
306
+ {
307
+ fetch_payload->exception = exception;
308
+ return GIT_ERROR;
309
+ }
310
+
311
+ static int clone_fetch_callback(const git_transfer_progress *stats, void *payload)
312
+ {
313
+ struct clone_fetch_callback_payload *fetch_payload = payload;
314
+ fetch_payload->stats = stats;
315
+ return rb_rescue(clone_fetch_callback_inner, (VALUE) fetch_payload,
316
+ clone_fetch_callback_rescue, (VALUE) fetch_payload);
317
+ }
318
+
319
+ static void parse_clone_options(git_clone_options *ret, VALUE rb_options_hash, struct clone_fetch_callback_payload *fetch_progress_payload)
320
+ {
321
+ if (!NIL_P(rb_options_hash)) {
322
+ VALUE val;
323
+
324
+ val = rb_hash_aref(rb_options_hash, CSTR2SYM("bare"));
325
+ if (RTEST(val))
326
+ ret->bare = 1;
327
+
328
+ val = rb_hash_aref(rb_options_hash, CSTR2SYM("progress"));
329
+ if (RTEST(val)) {
330
+ if (rb_respond_to(val, rb_intern("call"))) {
331
+ fetch_progress_payload->proc = val;
332
+ ret->fetch_progress_payload = fetch_progress_payload;
333
+ ret->fetch_progress_cb = clone_fetch_callback;
334
+ } else {
335
+ rb_raise(rb_eArgError, "Expected a Proc or an object that responds to call (:progress).");
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ /*
342
+ * call-seq:
343
+ * Repository.clone_at(url, local_path[, options]) -> repository
344
+ *
345
+ * Clone a repository from +url+ to +local_path+.
346
+ *
347
+ * The following options can be passed in the +options+ Hash:
348
+ *
349
+ * :bare ::
350
+ * If +true+, the clone will be created as a bare repository.
351
+ * Defaults to +false+.
352
+ *
353
+ * :progress ::
354
+ * A callback that will be executed to report clone progress information. It will be passed
355
+ * the amount of +total_objects+, +indexed_objects+, +received_objects+ and +received_bytes+.
356
+ *
357
+ * Example:
358
+ *
359
+ * progress = lambda { |total_objects, indexed_objects, received_objects, received_bytes|
360
+ * # ...
361
+ * }
362
+ * Repository.clone_at("https://github.com/libgit2/rugged.git", "./some/dir", :progress => progress)
363
+ */
364
+ static VALUE rb_git_repo_clone_at(int argc, VALUE *argv, VALUE klass)
365
+ {
366
+ VALUE url, local_path, rb_options_hash;
367
+ git_clone_options options = GIT_CLONE_OPTIONS_INIT;
368
+ struct clone_fetch_callback_payload fetch_payload;
369
+ git_repository *repo;
370
+ int error;
371
+
372
+ rb_scan_args(argc, argv, "21", &url, &local_path, &rb_options_hash);
373
+ Check_Type(url, T_STRING);
374
+ Check_Type(local_path, T_STRING);
375
+
376
+ fetch_payload.proc = Qnil;
377
+ fetch_payload.exception = Qnil;
378
+ parse_clone_options(&options, rb_options_hash, &fetch_payload);
379
+
380
+ error = git_clone(&repo, StringValueCStr(url), StringValueCStr(local_path), &options);
381
+ if (RTEST(fetch_payload.exception))
382
+ rb_exc_raise(fetch_payload.exception);
383
+ rugged_exception_check(error);
384
+
385
+ return rugged_repo_new(klass, repo);
386
+ }
387
+
275
388
  #define RB_GIT_REPO_OWNED_GET(_klass, _object) \
276
389
  VALUE rb_data = rb_iv_get(self, "@" #_object); \
277
390
  if (NIL_P(rb_data)) { \
@@ -307,86 +420,112 @@ static VALUE rb_git_repo_init_at(int argc, VALUE *argv, VALUE klass)
307
420
 
308
421
 
309
422
  /*
310
- * call-seq:
311
- * repo.index = idx
423
+ * call-seq:
424
+ * repo.index = idx
312
425
  *
313
- * Set the index for this +Repository+. +idx+ must be a instance of
314
- * +Rugged::Index+. This index will be used internally by all
315
- * operations that use the Git index on +repo+.
426
+ * Set the index for this +Repository+. +idx+ must be a instance of
427
+ * Rugged::Index. This index will be used internally by all
428
+ * operations that use the Git index on +repo+.
316
429
  *
317
- * Note that it's not necessary to set the +index+ for any repository;
318
- * by default repositories are loaded with the index file that can be
319
- * located on the +.git+ folder in the filesystem.
430
+ * Note that it's not necessary to set the +index+ for any repository;
431
+ * by default repositories are loaded with the index file that can be
432
+ * located on the +.git+ folder in the filesystem.
320
433
  */
321
434
  static VALUE rb_git_repo_set_index(VALUE self, VALUE rb_data)
322
435
  {
323
436
  RB_GIT_REPO_OWNED_SET(rb_cRuggedIndex, index);
324
437
  }
325
438
 
439
+ /*
440
+ * call-seq:
441
+ * repo.index -> idx
442
+ *
443
+ * Return the default index for this repository.
444
+ */
326
445
  static VALUE rb_git_repo_get_index(VALUE self)
327
446
  {
328
447
  RB_GIT_REPO_OWNED_GET(rb_cRuggedIndex, index);
329
448
  }
330
449
 
331
450
  /*
332
- * call-seq:
333
- * repo.config = cfg
451
+ * call-seq:
452
+ * repo.config = cfg
334
453
  *
335
- * Set the configuration file for this +Repository+. +cfg+ must be a instance of
336
- * +Rugged::Config+. This config file will be used internally by all
337
- * operations that need to lookup configuration settings on +repo+.
454
+ * Set the configuration file for this +Repository+. +cfg+ must be a instance of
455
+ * Rugged::Config. This config file will be used internally by all
456
+ * operations that need to lookup configuration settings on +repo+.
338
457
  *
339
- * Note that it's not necessary to set the +config+ for any repository;
340
- * by default repositories are loaded with their relevant config files
341
- * on the filesystem, and the corresponding global and system files if
342
- * they can be found.
458
+ * Note that it's not necessary to set the +config+ for any repository;
459
+ * by default repositories are loaded with their relevant config files
460
+ * on the filesystem, and the corresponding global and system files if
461
+ * they can be found.
343
462
  */
344
463
  static VALUE rb_git_repo_set_config(VALUE self, VALUE rb_data)
345
464
  {
346
465
  RB_GIT_REPO_OWNED_SET(rb_cRuggedConfig, config);
347
466
  }
348
467
 
468
+ /*
469
+ * call-seq:
470
+ * repo.config -> cfg
471
+ *
472
+ * Return a Rugged::Config object representing this repository's config.
473
+ */
349
474
  static VALUE rb_git_repo_get_config(VALUE self)
350
475
  {
351
476
  RB_GIT_REPO_OWNED_GET(rb_cRuggedConfig, config);
352
477
  }
353
478
 
354
479
  /*
355
- * call-seq:
356
- * repo.merge_base(oid1, oid2)
357
- * repo.merge_base(ref1, ref2)
358
- * repo.merge_base(commit1, commit2)
480
+ * call-seq:
481
+ * repo.merge_base(oid1, oid2, ...)
482
+ * repo.merge_base(ref1, ref2, ...)
483
+ * repo.merge_base(commit1, commit2, ...)
359
484
  *
360
- * Find a merge base, given two commits or oids.
361
- * Returns nil if a merge base is not found.
485
+ * Find a merge base, given two or more commits or oids.
486
+ * Returns nil if a merge base is not found.
362
487
  */
363
- static VALUE rb_git_repo_merge_base(VALUE self, VALUE obj1, VALUE obj2)
488
+ static VALUE rb_git_repo_merge_base(VALUE self, VALUE rb_args)
364
489
  {
365
- int error;
366
- git_oid oid1, oid2, base;
490
+ int error = GIT_OK, i;
367
491
  git_repository *repo;
492
+ git_oid base, *input_array = xmalloc(sizeof(git_oid) * RARRAY_LEN(rb_args));
493
+ int len = (int)RARRAY_LEN(rb_args);
494
+
495
+ if (len < 2)
496
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 2+)", len);
368
497
 
369
498
  Data_Get_Struct(self, git_repository, repo);
370
- rugged_oid_get(&oid1, repo, obj1);
371
- rugged_oid_get(&oid2, repo, obj2);
372
499
 
373
- error = git_merge_base(&base, repo, &oid1, &oid2);
500
+ for (i = 0; !error && i < len; ++i) {
501
+ error = rugged_oid_get(&input_array[i], repo, rb_ary_entry(rb_args, i));
502
+ }
503
+
504
+ if (error) {
505
+ xfree(input_array);
506
+ rugged_exception_check(error);
507
+ }
508
+
509
+ error = git_merge_base_many(&base, repo, input_array, len);
510
+ xfree(input_array);
511
+
374
512
  if (error == GIT_ENOTFOUND)
375
513
  return Qnil;
376
514
 
377
515
  rugged_exception_check(error);
516
+
378
517
  return rugged_create_oid(&base);
379
518
  }
380
519
 
381
520
  /*
382
- * call-seq:
383
- * repo.include?(oid) -> true or false
384
- * repo.exists?(oid) -> true or false
521
+ * call-seq:
522
+ * repo.include?(oid) -> true or false
523
+ * repo.exists?(oid) -> true or false
385
524
  *
386
- * Return whether an object with the given SHA1 OID (represented as
387
- * a 40-character string) exists in the repository.
525
+ * Return whether an object with the given SHA1 OID (represented as
526
+ * a 40-character string) exists in the repository.
388
527
  *
389
- * repo.include?("d8786bfc97485e8d7b19b21fb88c8ef1f199fc3f") #=> true
528
+ * repo.include?("d8786bfc97485e8d7b19b21fb88c8ef1f199fc3f") #=> true
390
529
  */
391
530
  static VALUE rb_git_repo_exists(VALUE self, VALUE hex)
392
531
  {
@@ -399,10 +538,10 @@ static VALUE rb_git_repo_exists(VALUE self, VALUE hex)
399
538
  Data_Get_Struct(self, git_repository, repo);
400
539
  Check_Type(hex, T_STRING);
401
540
 
402
- error = git_repository_odb(&odb, repo);
541
+ error = git_oid_fromstr(&oid, StringValueCStr(hex));
403
542
  rugged_exception_check(error);
404
543
 
405
- error = git_oid_fromstr(&oid, StringValueCStr(hex));
544
+ error = git_repository_odb(&odb, repo);
406
545
  rugged_exception_check(error);
407
546
 
408
547
  rb_result = git_odb_exists(odb, &oid) ? Qtrue : Qfalse;
@@ -411,6 +550,12 @@ static VALUE rb_git_repo_exists(VALUE self, VALUE hex)
411
550
  return rb_result;
412
551
  }
413
552
 
553
+ /*
554
+ * call-seq:
555
+ * repo.read(oid) -> str
556
+ *
557
+ * Read and return the raw data of the object identified by the given +oid+.
558
+ */
414
559
  static VALUE rb_git_repo_read(VALUE self, VALUE hex)
415
560
  {
416
561
  git_repository *repo;
@@ -426,6 +571,21 @@ static VALUE rb_git_repo_read(VALUE self, VALUE hex)
426
571
  return rugged_raw_read(repo, &oid);
427
572
  }
428
573
 
574
+ /*
575
+ * call-seq:
576
+ * repo.read_header(oid) -> hash
577
+ *
578
+ * Read and return the header information in +repo+'s ODB
579
+ * for the object identified by the given +oid+.
580
+ *
581
+ * Returns a Hash object with the following key/value pairs:
582
+ *
583
+ * :type ::
584
+ * A Symbol denoting the object's type. Possible values are:
585
+ * +:tree+, +:blob+, +:commit+ or +:tag+.
586
+ * :len ::
587
+ * A Number representing the object's length, in bytes.
588
+ */
429
589
  static VALUE rb_git_repo_read_header(VALUE self, VALUE hex)
430
590
  {
431
591
  git_repository *repo;
@@ -457,16 +617,16 @@ static VALUE rb_git_repo_read_header(VALUE self, VALUE hex)
457
617
  }
458
618
 
459
619
  /*
460
- * call-seq:
461
- * Repository.hash(buffer, type) -> oid
620
+ * call-seq:
621
+ * Repository.hash(buffer, type) -> oid
462
622
  *
463
- * Hash the contents of +buffer+ as raw bytes (ignoring any encoding
464
- * information) and adding the relevant header corresponding to +type+,
465
- * and return a hex string representing the result from the hash.
623
+ * Hash the contents of +buffer+ as raw bytes (ignoring any encoding
624
+ * information) and adding the relevant header corresponding to +type+,
625
+ * and return a hex string representing the result from the hash.
466
626
  *
467
- * Repository.hash('hello world', :commit) #=> "de5ba987198bcf2518885f0fc1350e5172cded78"
627
+ * Repository.hash('hello world', :commit) #=> "de5ba987198bcf2518885f0fc1350e5172cded78"
468
628
  *
469
- * Repository.hash('hello_world', :tag) #=> "9d09060c850defbc7711d08b57def0d14e742f4e"
629
+ * Repository.hash('hello_world', :tag) #=> "9d09060c850defbc7711d08b57def0d14e742f4e"
470
630
  */
471
631
  static VALUE rb_git_repo_hash(VALUE self, VALUE rb_buffer, VALUE rb_type)
472
632
  {
@@ -486,16 +646,16 @@ static VALUE rb_git_repo_hash(VALUE self, VALUE rb_buffer, VALUE rb_type)
486
646
  }
487
647
 
488
648
  /*
489
- * call-seq:
490
- * Repository.hash_file(path, type) -> oid
649
+ * call-seq:
650
+ * Repository.hash_file(path, type) -> oid
491
651
  *
492
- * Hash the contents of the file pointed at by +path+, assuming
493
- * that it'd be stored in the ODB with the given +type+, and return
494
- * a hex string representing the SHA1 OID resulting from the hash.
652
+ * Hash the contents of the file pointed at by +path+, assuming
653
+ * that it'd be stored in the ODB with the given +type+, and return
654
+ * a hex string representing the SHA1 OID resulting from the hash.
495
655
  *
496
- * Repository.hash_file('foo.txt', :commit) #=> "de5ba987198bcf2518885f0fc1350e5172cded78"
656
+ * Repository.hash_file('foo.txt', :commit) #=> "de5ba987198bcf2518885f0fc1350e5172cded78"
497
657
  *
498
- * Repository.hash_file('foo.txt', :tag) #=> "9d09060c850defbc7711d08b57def0d14e742f4e"
658
+ * Repository.hash_file('foo.txt', :tag) #=> "9d09060c850defbc7711d08b57def0d14e742f4e"
499
659
  */
500
660
  static VALUE rb_git_repo_hashfile(VALUE self, VALUE rb_path, VALUE rb_type)
501
661
  {
@@ -513,6 +673,17 @@ static VALUE rb_git_repo_hashfile(VALUE self, VALUE rb_path, VALUE rb_type)
513
673
  return rugged_create_oid(&oid);
514
674
  }
515
675
 
676
+ /*
677
+ * call-seq:
678
+ * repo.write(buffer, type) -> oid
679
+ *
680
+ * Write the data contained in the +buffer+ string as a raw object of the
681
+ * given +type+ into the repository's object database.
682
+ *
683
+ * +type+ can be either +:tag+, +:commit+, +:tree+ or +:blob+.
684
+ *
685
+ * Returns the newly created object's oid.
686
+ */
516
687
  static VALUE rb_git_repo_write(VALUE self, VALUE rb_buffer, VALUE rub_type)
517
688
  {
518
689
  git_repository *repo;
@@ -537,9 +708,9 @@ static VALUE rb_git_repo_write(VALUE self, VALUE rb_buffer, VALUE rub_type)
537
708
  rugged_exception_check(error);
538
709
 
539
710
  error = stream->write(stream, RSTRING_PTR(rb_buffer), RSTRING_LEN(rb_buffer));
540
- rugged_exception_check(error);
711
+ if (!error)
712
+ error = stream->finalize_write(&oid, stream);
541
713
 
542
- error = stream->finalize_write(&oid, stream);
543
714
  stream->free(stream);
544
715
  rugged_exception_check(error);
545
716
 
@@ -555,11 +726,11 @@ static VALUE rb_git_repo_write(VALUE self, VALUE rb_buffer, VALUE rub_type)
555
726
  return error ? Qtrue : Qfalse; \
556
727
 
557
728
  /*
558
- * call-seq:
559
- * repo.bare? -> true or false
729
+ * call-seq:
730
+ * repo.bare? -> true or false
560
731
  *
561
- * Return whether a repository is bare or not. A bare repository has no
562
- * working directory.
732
+ * Return whether a repository is bare or not. A bare repository has no
733
+ * working directory.
563
734
  */
564
735
  static VALUE rb_git_repo_is_bare(VALUE self)
565
736
  {
@@ -568,11 +739,11 @@ static VALUE rb_git_repo_is_bare(VALUE self)
568
739
 
569
740
 
570
741
  /*
571
- * call-seq:
572
- * repo.empty? -> true or false
742
+ * call-seq:
743
+ * repo.empty? -> true or false
573
744
  *
574
- * Return whether a repository is empty or not. An empty repository has just
575
- * been initialized and has no commits yet.
745
+ * Return whether a repository is empty or not. An empty repository has just
746
+ * been initialized and has no commits yet.
576
747
  */
577
748
  static VALUE rb_git_repo_is_empty(VALUE self)
578
749
  {
@@ -580,10 +751,10 @@ static VALUE rb_git_repo_is_empty(VALUE self)
580
751
  }
581
752
 
582
753
  /*
583
- * call-seq:
584
- * repo.head_detached? -> true or false
754
+ * call-seq:
755
+ * repo.head_detached? -> true or false
585
756
  *
586
- * Return whether the +HEAD+ of a repository is detached or not.
757
+ * Return whether the +HEAD+ of a repository is detached or not.
587
758
  */
588
759
  static VALUE rb_git_repo_head_detached(VALUE self)
589
760
  {
@@ -591,10 +762,10 @@ static VALUE rb_git_repo_head_detached(VALUE self)
591
762
  }
592
763
 
593
764
  /*
594
- * call-seq:
595
- * repo.head_orphan? -> true or false
765
+ * call-seq:
766
+ * repo.head_orphan? -> true or false
596
767
  *
597
- * Return whether the +HEAD+ of a repository is orphaned or not.
768
+ * Return whether the +HEAD+ of a repository is orphaned or not.
598
769
  */
599
770
  static VALUE rb_git_repo_head_orphan(VALUE self)
600
771
  {
@@ -602,33 +773,78 @@ static VALUE rb_git_repo_head_orphan(VALUE self)
602
773
  }
603
774
 
604
775
  /*
605
- * call-seq:
606
- * repo.path -> path
776
+ * call-seq:
777
+ * repo.head = str
778
+ *
779
+ * Make the repository's +HEAD+ point to the specified reference.
780
+ */
781
+ static VALUE rb_git_repo_set_head(VALUE self, VALUE rb_head)
782
+ {
783
+ git_repository *repo;
784
+ int error;
785
+
786
+ Data_Get_Struct(self, git_repository, repo);
787
+
788
+ Check_Type(rb_head, T_STRING);
789
+ error = git_repository_set_head(repo, StringValueCStr(rb_head));
790
+ rugged_exception_check(error);
791
+
792
+ return Qnil;
793
+ }
794
+
795
+ /*
796
+ * call-seq:
797
+ * repo.head -> ref
798
+ *
799
+ * Retrieve and resolve the reference pointed at by the repository's +HEAD+.
800
+ *
801
+ * Returns +nil+ if +HEAD+ is missing.
802
+ */
803
+ static VALUE rb_git_repo_get_head(VALUE self)
804
+ {
805
+ git_repository *repo;
806
+ git_reference *head;
807
+ int error;
808
+
809
+ Data_Get_Struct(self, git_repository, repo);
810
+
811
+ error = git_repository_head(&head, repo);
812
+ if (error == GIT_ENOTFOUND)
813
+ return Qnil;
814
+ else
815
+ rugged_exception_check(error);
816
+
817
+ return rugged_ref_new(rb_cRuggedReference, self, head);
818
+ }
819
+
820
+ /*
821
+ * call-seq:
822
+ * repo.path -> path
607
823
  *
608
- * Return the full, normalized path to this repository. For non-bare repositories,
609
- * this is the path of the actual +.git+ folder, not the working directory.
824
+ * Return the full, normalized path to this repository. For non-bare repositories,
825
+ * this is the path of the actual +.git+ folder, not the working directory.
610
826
  *
611
- * repo.path #=> "/home/foo/workthing/.git"
827
+ * repo.path #=> "/home/foo/workthing/.git"
612
828
  */
613
829
  static VALUE rb_git_repo_path(VALUE self)
614
830
  {
615
831
  git_repository *repo;
616
832
  Data_Get_Struct(self, git_repository, repo);
617
- return rugged_str_new2(git_repository_path(repo), NULL);
833
+ return rb_str_new_utf8(git_repository_path(repo));
618
834
  }
619
835
 
620
836
  /*
621
- * call-seq:
622
- * repo.workdir -> path or nil
837
+ * call-seq:
838
+ * repo.workdir -> path or nil
623
839
  *
624
- * Return the working directory for this repository, or +nil+ if
625
- * the repository is bare.
840
+ * Return the working directory for this repository, or +nil+ if
841
+ * the repository is bare.
626
842
  *
627
- * repo1.bare? #=> false
628
- * repo1.workdir # => "/home/foo/workthing/"
843
+ * repo1.bare? #=> false
844
+ * repo1.workdir #=> "/home/foo/workthing/"
629
845
  *
630
- * repo2.bare? #=> true
631
- * repo2.workdir #=> nil
846
+ * repo2.bare? #=> true
847
+ * repo2.workdir #=> nil
632
848
  */
633
849
  static VALUE rb_git_repo_workdir(VALUE self)
634
850
  {
@@ -638,24 +854,24 @@ static VALUE rb_git_repo_workdir(VALUE self)
638
854
  Data_Get_Struct(self, git_repository, repo);
639
855
  workdir = git_repository_workdir(repo);
640
856
 
641
- return workdir ? rugged_str_new2(workdir, NULL) : Qnil;
857
+ return workdir ? rb_str_new_utf8(workdir) : Qnil;
642
858
  }
643
859
 
644
860
  /*
645
- * call-seq:
646
- * repo.workdir = path
861
+ * call-seq:
862
+ * repo.workdir = path
647
863
  *
648
- * Sets the working directory of +repo+ to +path+. All internal
649
- * operations on +repo+ that affect the working directory will
650
- * instead use +path+.
864
+ * Sets the working directory of +repo+ to +path+. All internal
865
+ * operations on +repo+ that affect the working directory will
866
+ * instead use +path+.
651
867
  *
652
- * The +workdir+ can be set on bare repositories to temporarily
653
- * turn them into normal repositories.
868
+ * The +workdir+ can be set on bare repositories to temporarily
869
+ * turn them into normal repositories.
654
870
  *
655
- * repo.bare? #=> true
656
- * repo.workdir = "/tmp/workdir"
657
- * repo.bare? #=> false
658
- * repo.checkout
871
+ * repo.bare? #=> true
872
+ * repo.workdir = "/tmp/workdir"
873
+ * repo.bare? #=> false
874
+ * repo.checkout
659
875
  */
660
876
  static VALUE rb_git_repo_set_workdir(VALUE self, VALUE rb_workdir)
661
877
  {
@@ -672,19 +888,19 @@ static VALUE rb_git_repo_set_workdir(VALUE self, VALUE rb_workdir)
672
888
  }
673
889
 
674
890
  /*
675
- * call-seq:
676
- * Repository.discover(path = nil, across_fs = true) -> repository
891
+ * call-seq:
892
+ * Repository.discover(path = nil, across_fs = true) -> repository
677
893
  *
678
- * Traverse +path+ upwards until a Git working directory with a +.git+
679
- * folder has been found, open it and return it as a +Repository+
680
- * object.
894
+ * Traverse +path+ upwards until a Git working directory with a +.git+
895
+ * folder has been found, open it and return it as a +Repository+
896
+ * object.
681
897
  *
682
- * If +path+ is +nil+, the current working directory will be used as
683
- * a starting point.
898
+ * If +path+ is +nil+, the current working directory will be used as
899
+ * a starting point.
684
900
  *
685
- * If +across_fs+ is +true+, the traversal won't stop when reaching
686
- * a different device than the one that contained +path+ (only applies
687
- * to UNIX-based OSses).
901
+ * If +across_fs+ is +true+, the traversal won't stop when reaching
902
+ * a different device than the one that contained +path+ (only applies
903
+ * to UNIX-based OSses).
688
904
  */
689
905
  static VALUE rb_git_repo_discover(int argc, VALUE *argv, VALUE self)
690
906
  {
@@ -713,7 +929,7 @@ static VALUE rb_git_repo_discover(int argc, VALUE *argv, VALUE self)
713
929
  );
714
930
 
715
931
  rugged_exception_check(error);
716
- return rugged_str_new2(repository_path, NULL);
932
+ return rb_str_new_utf8(repository_path);
717
933
  }
718
934
 
719
935
  static VALUE flags_to_rb(unsigned int flags)
@@ -744,48 +960,47 @@ static VALUE flags_to_rb(unsigned int flags)
744
960
  static int rugged__status_cb(const char *path, unsigned int flags, void *payload)
745
961
  {
746
962
  rb_funcall((VALUE)payload, rb_intern("call"), 2,
747
- rugged_str_new2(path, NULL),
748
- flags_to_rb(flags)
963
+ rb_str_new_utf8(path), flags_to_rb(flags)
749
964
  );
750
965
 
751
966
  return GIT_OK;
752
967
  }
753
968
 
754
969
  /*
755
- * call-seq:
756
- * repo.status { |status_data| block }
757
- * repo.status(path) -> status_data
970
+ * call-seq:
971
+ * repo.status { |status_data| block }
972
+ * repo.status(path) -> status_data
758
973
  *
759
- * Returns the status for one or more files in the working directory
760
- * of the repository. This is equivalent to the +git status+ command.
974
+ * Returns the status for one or more files in the working directory
975
+ * of the repository. This is equivalent to the +git status+ command.
761
976
  *
762
- * The returned +status_data+ is always an array containing one or more
763
- * status flags as Ruby symbols. Possible flags are:
977
+ * The returned +status_data+ is always an array containing one or more
978
+ * status flags as Ruby symbols. Possible flags are:
764
979
  *
765
- * - +:index_new+: the file is new in the index
766
- * - +:index_modified+: the file has been modified in the index
767
- * - +:index_deleted+: the file has been deleted from the index
768
- * - +:worktree_new+: the file is new in the working directory
769
- * - +:worktree_modified+: the file has been modified in the working directory
770
- * - +:worktree_deleted+: the file has been deleted from the working directory
980
+ * - +:index_new+: the file is new in the index
981
+ * - +:index_modified+: the file has been modified in the index
982
+ * - +:index_deleted+: the file has been deleted from the index
983
+ * - +:worktree_new+: the file is new in the working directory
984
+ * - +:worktree_modified+: the file has been modified in the working directory
985
+ * - +:worktree_deleted+: the file has been deleted from the working directory
771
986
  *
772
- * If a +block+ is given, status information will be gathered for every
773
- * single file on the working dir. The +block+ will be called with the
774
- * status data for each file.
987
+ * If a +block+ is given, status information will be gathered for every
988
+ * single file on the working dir. The +block+ will be called with the
989
+ * status data for each file.
775
990
  *
776
- * repo.status { |status_data| puts status_data.inspect }
991
+ * repo.status { |status_data| puts status_data.inspect }
777
992
  *
778
- * results in, for example:
993
+ * results in, for example:
779
994
  *
780
- * [:index_new, :worktree_new]
781
- * [:worktree_modified]
995
+ * [:index_new, :worktree_new]
996
+ * [:worktree_modified]
782
997
  *
783
- * If a +path+ is given instead, the function will return the +status_data+ for
784
- * the file pointed to by path, or raise an exception if the path doesn't exist.
998
+ * If a +path+ is given instead, the function will return the +status_data+ for
999
+ * the file pointed to by path, or raise an exception if the path doesn't exist.
785
1000
  *
786
- * +path+ must be relative to the repository's working directory.
1001
+ * +path+ must be relative to the repository's working directory.
787
1002
  *
788
- * repo.status('src/diff.c') #=> [:index_new, :worktree_new]
1003
+ * repo.status('src/diff.c') #=> [:index_new, :worktree_new]
789
1004
  */
790
1005
  static VALUE rb_git_repo_status(int argc, VALUE *argv, VALUE self)
791
1006
  {
@@ -821,24 +1036,25 @@ static VALUE rb_git_repo_status(int argc, VALUE *argv, VALUE self)
821
1036
 
822
1037
  static int rugged__each_id_cb(const git_oid *id, void *payload)
823
1038
  {
824
- rb_yield(rugged_create_oid(id));
825
- return 0;
1039
+ int *exception = (int *)payload;
1040
+ rb_protect(rb_yield, rugged_create_oid(id), exception);
1041
+ return *exception ? GIT_ERROR : GIT_OK;
826
1042
  }
827
1043
 
828
1044
  /*
829
- * call-seq:
830
- * repo.each_id { |id| block }
831
- * repo.each_id -> Iterator
1045
+ * call-seq:
1046
+ * repo.each_id { |id| block }
1047
+ * repo.each_id -> Iterator
832
1048
  *
833
- * Call the given +block+ once with every object ID found in +repo+
834
- * and all its alternates. Object IDs are passed as 40-character
835
- * strings.
1049
+ * Call the given +block+ once with every object ID found in +repo+
1050
+ * and all its alternates. Object IDs are passed as 40-character
1051
+ * strings.
836
1052
  */
837
1053
  static VALUE rb_git_repo_each_id(VALUE self)
838
1054
  {
839
1055
  git_repository *repo;
840
1056
  git_odb *odb;
841
- int error;
1057
+ int error, exception = 0;
842
1058
 
843
1059
  if (!rb_block_given_p())
844
1060
  return rb_funcall(self, rb_intern("to_enum"), 1, CSTR2SYM("each_id"));
@@ -848,10 +1064,13 @@ static VALUE rb_git_repo_each_id(VALUE self)
848
1064
  error = git_repository_odb(&odb, repo);
849
1065
  rugged_exception_check(error);
850
1066
 
851
- error = git_odb_foreach(odb, &rugged__each_id_cb, NULL);
1067
+ error = git_odb_foreach(odb, &rugged__each_id_cb, &exception);
852
1068
  git_odb_free(odb);
853
1069
 
1070
+ if (exception)
1071
+ rb_jump_tag(exception);
854
1072
  rugged_exception_check(error);
1073
+
855
1074
  return Qnil;
856
1075
  }
857
1076
 
@@ -875,22 +1094,27 @@ static int parse_reset_type(VALUE rb_reset_type)
875
1094
  }
876
1095
 
877
1096
  /*
878
- * call-seq:
879
- * repo.reset(target, reset_type) -> nil
880
- *
881
- * Sets the current head to the specified commit oid and optionally
882
- * resets the index and working tree to match.
883
- * - +target+: Rugged::Commit, Rugged::Tag or rev that resolves to a commit or tag object
884
- * - +reset_type+: :soft, :mixed: or :hard
885
- * [:soft] the head will be moved to the commit.
886
- * [:mixed] will trigger a +:soft+ reset, plus the index will be replaced
887
- * with the content of the commit tree.
888
- * [:hard] will trigger a +:mixed+ reset and the working directory will be
889
- * replaced with the content of the index. (Untracked and ignored files
890
- * will be left alone)
891
- *
892
- * Examples:
893
- * repo.reset('origin/master', :hard) #=> nil
1097
+ * call-seq:
1098
+ * repo.reset(target, reset_type) -> nil
1099
+ *
1100
+ * Sets the current head to the specified commit oid and optionally
1101
+ * resets the index and working tree to match.
1102
+ * - +target+: Rugged::Commit, Rugged::Tag or rev that resolves to a commit or tag object
1103
+ * - +reset_type+: +:soft+, +:mixed+ or +:hard+
1104
+ *
1105
+ * [:soft]
1106
+ * the head will be moved to the commit.
1107
+ * [:mixed]
1108
+ * will trigger a +:soft+ reset, plus the index will be replaced
1109
+ * with the content of the commit tree.
1110
+ * [:hard]
1111
+ * will trigger a +:mixed+ reset and the working directory will be
1112
+ * replaced with the content of the index. (Untracked and ignored files
1113
+ * will be left alone)
1114
+ *
1115
+ * Examples:
1116
+ *
1117
+ * repo.reset('origin/master', :hard) #=> nil
894
1118
  */
895
1119
  static VALUE rb_git_repo_reset(VALUE self, VALUE rb_target, VALUE rb_reset_type)
896
1120
  {
@@ -913,20 +1137,20 @@ static VALUE rb_git_repo_reset(VALUE self, VALUE rb_target, VALUE rb_reset_type)
913
1137
  }
914
1138
 
915
1139
  /*
916
- * call-seq:
917
- * repo.reset_path(pathspecs, target=nil) -> nil
1140
+ * call-seq:
1141
+ * repo.reset_path(pathspecs, target=nil) -> nil
918
1142
  *
919
- * Updates entries in the index from the +target+ commit tree, matching
920
- * the given +pathspecs+.
1143
+ * Updates entries in the index from the +target+ commit tree, matching
1144
+ * the given +pathspecs+.
921
1145
  *
922
- * Passing a nil +target+ will result in removing
923
- * entries in the index matching the provided pathspecs.
1146
+ * Passing a nil +target+ will result in removing
1147
+ * entries in the index matching the provided pathspecs.
924
1148
  *
925
- * - +pahtspecs+: list of pathspecs to operate on (+String+ or +Array+ of +String+ objects)
926
- * - +target+(optional): Rugged::Commit, Rugged::Tag or rev that resolves to a commit or tag object.
1149
+ * - +pathspecs+: list of pathspecs to operate on (+String+ or +Array+ of +String+ objects)
1150
+ * - +target+(optional): Rugged::Commit, Rugged::Tag or rev that resolves to a commit or tag object.
927
1151
  *
928
- * Examples:
929
- * reset_path(File.join('subdir','file.txt'), '441034f860c1d5d90e4188d11ae0d325176869a8') #=> nil
1152
+ * Examples:
1153
+ * reset_path(File.join('subdir','file.txt'), '441034f860c1d5d90e4188d11ae0d325176869a8') #=> nil
930
1154
  */
931
1155
  static VALUE rb_git_repo_reset_path(int argc, VALUE *argv, VALUE self)
932
1156
  {
@@ -975,17 +1199,21 @@ static int rugged__push_status_cb(const char *ref, const char *msg, void *payloa
975
1199
  {
976
1200
  VALUE rb_result_hash = (VALUE)payload;
977
1201
  if (msg != NULL)
978
- rb_hash_aset(rb_result_hash, rugged_str_new2(ref, rb_utf8_encoding()),
979
- rugged_str_new2(msg, NULL));
1202
+ rb_hash_aset(rb_result_hash, rb_str_new_utf8(ref), rb_str_new_utf8(msg));
1203
+
980
1204
  return GIT_OK;
981
1205
  }
982
1206
 
983
1207
  /*
984
- * call-seq:
985
- * repo.push("origin", ["refs/heads/master", ":refs/heads/to_be_deleted"])
1208
+ * call-seq:
1209
+ * repo.push(remote, refspecs) -> hash
986
1210
  *
987
- * Pushes the given refspecs to the given remote. Returns a hash that contains key-value pairs that
988
- * reflect pushed refs and error messages, if applicable.
1211
+ * Pushes the given +refspecs+ to the given +remote+. Returns a hash that contains
1212
+ * key-value pairs that reflect pushed refs and error messages, if applicable.
1213
+ *
1214
+ * Example:
1215
+ *
1216
+ * repo.push("origin", ["refs/heads/master", ":refs/heads/to_be_deleted"])
989
1217
  */
990
1218
  static VALUE rb_git_repo_push(VALUE self, VALUE rb_remote, VALUE rb_refspecs)
991
1219
  {
@@ -1060,8 +1288,106 @@ cleanup:
1060
1288
  return rb_result;
1061
1289
  }
1062
1290
 
1063
- void Init_rugged_repo()
1291
+ /*
1292
+ * call-seq:
1293
+ * repo.close -> nil
1294
+ *
1295
+ * Frees all the resources used by this repository immediately. The repository can
1296
+ * still be used after this call. Resources will be opened as necessary.
1297
+ *
1298
+ * It is not required to call this method explicitly. Repositories are closed
1299
+ * automatically before garbage collection
1300
+ */
1301
+ static VALUE rb_git_repo_close(VALUE self)
1302
+ {
1303
+ git_repository *repo;
1304
+ Data_Get_Struct(self, git_repository, repo);
1305
+
1306
+ git_repository__cleanup(repo);
1307
+
1308
+ return Qnil;
1309
+ }
1310
+
1311
+ /*
1312
+ * call-seq:
1313
+ * repo.namespace = new_namespace
1314
+ *
1315
+ * Sets the active namespace for the repository.
1316
+ * If set to nil, no namespace will be active.
1317
+ */
1318
+ static VALUE rb_git_repo_set_namespace(VALUE self, VALUE rb_namespace)
1319
+ {
1320
+ git_repository *repo;
1321
+ int error;
1322
+
1323
+ Data_Get_Struct(self, git_repository, repo);
1324
+
1325
+ if (!NIL_P(rb_namespace)) {
1326
+ Check_Type(rb_namespace, T_STRING);
1327
+ error = git_repository_set_namespace(repo, StringValueCStr(rb_namespace));
1328
+ } else {
1329
+ error = git_repository_set_namespace(repo, NULL);
1330
+ }
1331
+ rugged_exception_check(error);
1332
+
1333
+ return Qnil;
1334
+ }
1335
+
1336
+ /*
1337
+ * call-seq:
1338
+ * repo.namespace -> str
1339
+ *
1340
+ * Returns the active namespace for the repository.
1341
+ */
1342
+ static VALUE rb_git_repo_get_namespace(VALUE self)
1343
+ {
1344
+ git_repository *repo;
1345
+ const char *namespace;
1346
+
1347
+ Data_Get_Struct(self, git_repository, repo);
1348
+
1349
+ namespace = git_repository_get_namespace(repo);
1350
+ return namespace ? rb_str_new_utf8(namespace) : Qnil;
1351
+ }
1352
+
1353
+ /*
1354
+ * call-seq:
1355
+ * repo.ahead_behind(local, upstream) -> Array
1356
+ *
1357
+ * Returns a 2 element Array containing the number of commits
1358
+ * that the upstream object is ahead and behind the local object.
1359
+ *
1360
+ * +local+ and +upstream+ can either be strings containing SHA1 OIDs or
1361
+ * Rugged::Object instances.
1362
+ */
1363
+ static VALUE rb_git_repo_ahead_behind(VALUE self, VALUE rb_local, VALUE rb_upstream) {
1364
+ git_repository *repo;
1365
+ int error;
1366
+ git_oid local, upstream;
1367
+ size_t ahead, behind;
1368
+ VALUE rb_result;
1369
+
1370
+ Data_Get_Struct(self, git_repository, repo);
1371
+
1372
+ error = rugged_oid_get(&local, repo, rb_local);
1373
+ rugged_exception_check(error);
1374
+
1375
+ error = rugged_oid_get(&upstream, repo, rb_upstream);
1376
+ rugged_exception_check(error);
1377
+
1378
+ error = git_graph_ahead_behind(&ahead, &behind, repo, &local, &upstream);
1379
+ rugged_exception_check(error);
1380
+
1381
+ rb_result = rb_ary_new2(2);
1382
+ rb_ary_push(rb_result, INT2FIX((int) ahead));
1383
+ rb_ary_push(rb_result, INT2FIX((int) behind));
1384
+ return rb_result;
1385
+ }
1386
+
1387
+ void Init_rugged_repo(void)
1064
1388
  {
1389
+ id_call = rb_intern("call");
1390
+
1065
1391
  rb_cRuggedRepo = rb_define_class_under(rb_mRugged, "Repository", rb_cObject);
1066
1392
 
1067
1393
  rb_define_singleton_method(rb_cRuggedRepo, "new", rb_git_repo_new, -1);
@@ -1070,6 +1396,9 @@ void Init_rugged_repo()
1070
1396
  rb_define_singleton_method(rb_cRuggedRepo, "hash_file", rb_git_repo_hashfile, 2);
1071
1397
  rb_define_singleton_method(rb_cRuggedRepo, "init_at", rb_git_repo_init_at, -1);
1072
1398
  rb_define_singleton_method(rb_cRuggedRepo, "discover", rb_git_repo_discover, -1);
1399
+ rb_define_singleton_method(rb_cRuggedRepo, "clone_at", rb_git_repo_clone_at, -1);
1400
+
1401
+ rb_define_method(rb_cRuggedRepo, "close", rb_git_repo_close, 0);
1073
1402
 
1074
1403
  rb_define_method(rb_cRuggedRepo, "exists?", rb_git_repo_exists, 1);
1075
1404
  rb_define_method(rb_cRuggedRepo, "include?", rb_git_repo_exists, 1);
@@ -1096,11 +1425,18 @@ void Init_rugged_repo()
1096
1425
 
1097
1426
  rb_define_method(rb_cRuggedRepo, "head_detached?", rb_git_repo_head_detached, 0);
1098
1427
  rb_define_method(rb_cRuggedRepo, "head_orphan?", rb_git_repo_head_orphan, 0);
1428
+ rb_define_method(rb_cRuggedRepo, "head=", rb_git_repo_set_head, 1);
1429
+ rb_define_method(rb_cRuggedRepo, "head", rb_git_repo_get_head, 0);
1099
1430
 
1100
- rb_define_method(rb_cRuggedRepo, "merge_base", rb_git_repo_merge_base, 2);
1431
+ rb_define_method(rb_cRuggedRepo, "merge_base", rb_git_repo_merge_base, -2);
1101
1432
  rb_define_method(rb_cRuggedRepo, "reset", rb_git_repo_reset, 2);
1102
1433
  rb_define_method(rb_cRuggedRepo, "reset_path", rb_git_repo_reset_path, -1);
1103
1434
 
1435
+ rb_define_method(rb_cRuggedRepo, "namespace=", rb_git_repo_set_namespace, 1);
1436
+ rb_define_method(rb_cRuggedRepo, "namespace", rb_git_repo_get_namespace, 0);
1437
+
1438
+ rb_define_method(rb_cRuggedRepo, "ahead_behind", rb_git_repo_ahead_behind, 2);
1439
+
1104
1440
  rb_cRuggedOdbObject = rb_define_class_under(rb_mRugged, "OdbObject", rb_cObject);
1105
1441
  rb_define_method(rb_cRuggedOdbObject, "data", rb_git_odbobj_data, 0);
1106
1442
  rb_define_method(rb_cRuggedOdbObject, "len", rb_git_odbobj_size, 0);