rdavila-rugged 0.24.0b13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +619 -0
  4. data/ext/rugged/extconf.rb +105 -0
  5. data/ext/rugged/rugged.c +527 -0
  6. data/ext/rugged/rugged.h +185 -0
  7. data/ext/rugged/rugged_backend.c +34 -0
  8. data/ext/rugged/rugged_blame.c +292 -0
  9. data/ext/rugged/rugged_blob.c +638 -0
  10. data/ext/rugged/rugged_branch.c +195 -0
  11. data/ext/rugged/rugged_branch_collection.c +408 -0
  12. data/ext/rugged/rugged_commit.c +691 -0
  13. data/ext/rugged/rugged_config.c +404 -0
  14. data/ext/rugged/rugged_cred.c +148 -0
  15. data/ext/rugged/rugged_diff.c +686 -0
  16. data/ext/rugged/rugged_diff_delta.c +105 -0
  17. data/ext/rugged/rugged_diff_hunk.c +103 -0
  18. data/ext/rugged/rugged_diff_line.c +83 -0
  19. data/ext/rugged/rugged_index.c +1255 -0
  20. data/ext/rugged/rugged_note.c +376 -0
  21. data/ext/rugged/rugged_object.c +383 -0
  22. data/ext/rugged/rugged_patch.c +245 -0
  23. data/ext/rugged/rugged_reference.c +396 -0
  24. data/ext/rugged/rugged_reference_collection.c +446 -0
  25. data/ext/rugged/rugged_remote.c +691 -0
  26. data/ext/rugged/rugged_remote_collection.c +457 -0
  27. data/ext/rugged/rugged_repo.c +2669 -0
  28. data/ext/rugged/rugged_revwalk.c +495 -0
  29. data/ext/rugged/rugged_settings.c +155 -0
  30. data/ext/rugged/rugged_signature.c +106 -0
  31. data/ext/rugged/rugged_submodule.c +852 -0
  32. data/ext/rugged/rugged_submodule_collection.c +384 -0
  33. data/ext/rugged/rugged_tag.c +251 -0
  34. data/ext/rugged/rugged_tag_collection.c +347 -0
  35. data/ext/rugged/rugged_tree.c +919 -0
  36. data/lib/rugged.rb +23 -0
  37. data/lib/rugged/attributes.rb +41 -0
  38. data/lib/rugged/blob.rb +28 -0
  39. data/lib/rugged/branch.rb +19 -0
  40. data/lib/rugged/commit.rb +54 -0
  41. data/lib/rugged/console.rb +9 -0
  42. data/lib/rugged/credentials.rb +43 -0
  43. data/lib/rugged/diff.rb +20 -0
  44. data/lib/rugged/diff/delta.rb +53 -0
  45. data/lib/rugged/diff/hunk.rb +18 -0
  46. data/lib/rugged/diff/line.rb +47 -0
  47. data/lib/rugged/index.rb +13 -0
  48. data/lib/rugged/object.rb +7 -0
  49. data/lib/rugged/patch.rb +36 -0
  50. data/lib/rugged/reference.rb +7 -0
  51. data/lib/rugged/remote.rb +4 -0
  52. data/lib/rugged/repository.rb +227 -0
  53. data/lib/rugged/submodule_collection.rb +48 -0
  54. data/lib/rugged/tag.rb +50 -0
  55. data/lib/rugged/tree.rb +38 -0
  56. data/lib/rugged/version.rb +3 -0
  57. data/lib/rugged/walker.rb +5 -0
  58. metadata +146 -0
@@ -0,0 +1,185 @@
1
+ /*
2
+ * The MIT License
3
+ *
4
+ * Copyright (c) 2014 GitHub, Inc
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ */
24
+
25
+ #ifndef __H_RUGGED_BINDINGS__
26
+ #define __H_RUGGED_BINDINGS__
27
+
28
+ // tell rbx not to use it's caching compat layer
29
+ // by doing this we're making a promize to RBX that
30
+ // we'll never modify the pointers we get back from RSTRING_PTR
31
+ #define RSTRING_NOT_MODIFIED
32
+
33
+ #include <ruby.h>
34
+ #ifndef HAVE_RUBY_ENCODING_H
35
+ #error "Rugged requires Ruby 1.9+ to build"
36
+ #else
37
+ #include <ruby/encoding.h>
38
+ #endif
39
+
40
+ #include <assert.h>
41
+ #include <git2.h>
42
+ #include <git2/odb_backend.h>
43
+
44
+ #define rb_str_new_utf8(str) rb_enc_str_new(str, strlen(str), rb_utf8_encoding())
45
+ #define CSTR2SYM(s) (ID2SYM(rb_intern((s))))
46
+
47
+ /*
48
+ * Initialization functions
49
+ */
50
+ void Init_rugged_object(void);
51
+ void Init_rugged_branch(void);
52
+ void Init_rugged_branch_collection(void);
53
+ void Init_rugged_commit(void);
54
+ void Init_rugged_tree(void);
55
+ void Init_rugged_tag(void);
56
+ void Init_rugged_tag_collection(void);
57
+ void Init_rugged_blob(void);
58
+ void Init_rugged_index(void);
59
+ void Init_rugged_repo(void);
60
+ void Init_rugged_revwalk(void);
61
+ void Init_rugged_reference(void);
62
+ void Init_rugged_reference_collection(void);
63
+ void Init_rugged_config(void);
64
+ void Init_rugged_remote(void);
65
+ void Init_rugged_remote_collection(void);
66
+ void Init_rugged_notes(void);
67
+ void Init_rugged_settings(void);
68
+ void Init_rugged_submodule(void);
69
+ void Init_rugged_submodule_collection(void);
70
+ void Init_rugged_diff(void);
71
+ void Init_rugged_patch(void);
72
+ void Init_rugged_diff_delta(void);
73
+ void Init_rugged_diff_hunk(void);
74
+ void Init_rugged_diff_line(void);
75
+ void Init_rugged_blame(void);
76
+ void Init_rugged_cred(void);
77
+ void Init_rugged_backend(void);
78
+
79
+ VALUE rb_git_object_init(git_otype type, int argc, VALUE *argv, VALUE self);
80
+
81
+ VALUE rugged_raw_read(git_repository *repo, const git_oid *oid);
82
+
83
+ VALUE rugged_signature_new(const git_signature *sig, const char *encoding_name);
84
+
85
+ VALUE rugged_repo_new(VALUE klass, git_repository *repo);
86
+ VALUE rugged_index_new(VALUE klass, VALUE owner, git_index *index);
87
+ VALUE rugged_config_new(VALUE klass, VALUE owner, git_config *cfg);
88
+ VALUE rugged_object_new(VALUE owner, git_object *object);
89
+ VALUE rugged_object_rev_parse(VALUE rb_repo, VALUE rb_spec, int as_obj);
90
+ VALUE rugged_ref_new(VALUE klass, VALUE owner, git_reference *ref);
91
+ VALUE rugged_diff_new(VALUE klass, VALUE owner, git_diff *diff);
92
+ VALUE rugged_patch_new(VALUE owner, git_patch *patch);
93
+ VALUE rugged_diff_delta_new(VALUE owner, const git_diff_delta *delta);
94
+ VALUE rugged_diff_hunk_new(VALUE owner, size_t hunk_idx, const git_diff_hunk *hunk, size_t lines_in_hunk);
95
+ VALUE rugged_diff_line_new(const git_diff_line *line);
96
+ VALUE rugged_remote_new(VALUE owner, git_remote *remote);
97
+ VALUE rb_git_delta_file_fromC(const git_diff_file *file);
98
+
99
+ void rugged_parse_diff_options(git_diff_options *opts, VALUE rb_options);
100
+ void rugged_parse_merge_options(git_merge_options *opts, VALUE rb_options);
101
+
102
+ void rugged_cred_extract(git_cred **cred, int allowed_types, VALUE rb_credential);
103
+
104
+ VALUE rugged_otype_new(git_otype t);
105
+ git_otype rugged_otype_get(VALUE rb_type);
106
+
107
+ git_signature *rugged_signature_get(VALUE rb_person, git_repository *repo);
108
+ git_object *rugged_object_get(git_repository *repo, VALUE object_value, git_otype type);
109
+ int rugged_oid_get(git_oid *oid, git_repository *repo, VALUE p);
110
+
111
+ void rugged_rb_ary_to_strarray(VALUE rb_array, git_strarray *str_array);
112
+ VALUE rugged_strarray_to_rb_ary(git_strarray *str_array);
113
+
114
+ static inline void rugged_set_owner(VALUE object, VALUE owner)
115
+ {
116
+ rb_iv_set(object, "@owner", owner);
117
+ }
118
+
119
+ static inline VALUE rugged_owner(VALUE object)
120
+ {
121
+ return rb_iv_get(object, "@owner");
122
+ }
123
+
124
+ extern void rugged_exception_raise(void);
125
+
126
+ static inline void rugged_exception_check(int errorcode)
127
+ {
128
+ if (errorcode < 0)
129
+ rugged_exception_raise();
130
+ }
131
+
132
+ static inline int rugged_parse_bool(VALUE boolean)
133
+ {
134
+ if (TYPE(boolean) != T_TRUE && TYPE(boolean) != T_FALSE)
135
+ rb_raise(rb_eTypeError, "Expected boolean value");
136
+
137
+ return boolean ? 1 : 0;
138
+ }
139
+
140
+ extern VALUE rb_cRuggedRepo;
141
+
142
+ VALUE rugged__block_yield_splat(VALUE args);
143
+
144
+ struct rugged_cb_payload
145
+ {
146
+ VALUE rb_data;
147
+ int exception;
148
+ };
149
+
150
+ struct rugged_remote_cb_payload
151
+ {
152
+ VALUE progress;
153
+ VALUE completion;
154
+ VALUE transfer_progress;
155
+ VALUE update_tips;
156
+ VALUE credentials;
157
+ VALUE result;
158
+ int exception;
159
+ };
160
+
161
+ void rugged_remote_init_callbacks_and_payload_from_options(
162
+ VALUE rb_options,
163
+ git_remote_callbacks *callbacks,
164
+ struct rugged_remote_cb_payload *payload);
165
+
166
+ static inline void rugged_check_repo(VALUE rb_repo)
167
+ {
168
+ if (!rb_obj_is_kind_of(rb_repo, rb_cRuggedRepo))
169
+ rb_raise(rb_eTypeError, "Expecting a Rugged Repository");
170
+ }
171
+
172
+ static inline VALUE rugged_create_oid(const git_oid *oid)
173
+ {
174
+ char out[40];
175
+ git_oid_fmt(out, oid);
176
+ return rb_str_new(out, 40);
177
+ }
178
+
179
+
180
+ typedef struct _rugged_backend {
181
+ int (* odb_backend)(git_odb_backend **backend_out, struct _rugged_backend *backend, const char* path);
182
+ int (* refdb_backend)(git_refdb_backend **backend_out, struct _rugged_backend *backend, const char* path);
183
+ } rugged_backend;
184
+
185
+ #endif
@@ -0,0 +1,34 @@
1
+ /*
2
+ * The MIT License
3
+ *
4
+ * Copyright (c) 2014 GitHub, Inc
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ */
24
+
25
+ #include "rugged.h"
26
+
27
+ extern VALUE rb_mRugged;
28
+
29
+ VALUE rb_cRuggedBackend;
30
+
31
+ void Init_rugged_backend(void)
32
+ {
33
+ rb_cRuggedBackend = rb_define_class_under(rb_mRugged, "Backend", rb_cObject);
34
+ }
@@ -0,0 +1,292 @@
1
+ /*
2
+ * The MIT License
3
+ *
4
+ * Copyright (c) 2014 GitHub, Inc
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ */
24
+
25
+ #include "rugged.h"
26
+
27
+ extern VALUE rb_mRugged;
28
+ VALUE rb_cRuggedBlame;
29
+
30
+ static VALUE rb_git_blame_hunk_fromC(const git_blame_hunk *hunk)
31
+ {
32
+ VALUE rb_hunk;
33
+ if (!hunk) {
34
+ return Qnil;
35
+ }
36
+
37
+ rb_hunk = rb_hash_new();
38
+ rb_hash_aset(rb_hunk, CSTR2SYM("lines_in_hunk"), UINT2NUM(hunk->lines_in_hunk));
39
+
40
+ rb_hash_aset(rb_hunk, CSTR2SYM("final_commit_id"), rugged_create_oid(&(hunk->final_commit_id)));
41
+ rb_hash_aset(rb_hunk, CSTR2SYM("final_start_line_number"), UINT2NUM(hunk->final_start_line_number));
42
+ rb_hash_aset(rb_hunk, CSTR2SYM("final_signature"), hunk->final_signature ? rugged_signature_new(hunk->final_signature, NULL) : Qnil);
43
+
44
+ rb_hash_aset(rb_hunk, CSTR2SYM("orig_commit_id"), rugged_create_oid(&(hunk->orig_commit_id)));
45
+ rb_hash_aset(rb_hunk, CSTR2SYM("orig_path"), hunk->orig_path ? rb_str_new2(hunk->orig_path) : Qnil);
46
+ rb_hash_aset(rb_hunk, CSTR2SYM("orig_start_line_number"), UINT2NUM(hunk->orig_start_line_number));
47
+ rb_hash_aset(rb_hunk, CSTR2SYM("orig_signature"), hunk->orig_signature ? rugged_signature_new(hunk->orig_signature, NULL) : Qnil);
48
+
49
+ rb_hash_aset(rb_hunk, CSTR2SYM("boundary"), hunk->boundary ? Qtrue : Qfalse);
50
+
51
+ return rb_hunk;
52
+ }
53
+
54
+ static void rugged_parse_blame_options(git_blame_options *opts, git_repository *repo, VALUE rb_options)
55
+ {
56
+ if (!NIL_P(rb_options)) {
57
+ VALUE rb_value;
58
+ Check_Type(rb_options, T_HASH);
59
+
60
+ rb_value = rb_hash_aref(rb_options, CSTR2SYM("min_line"));
61
+ if (!NIL_P(rb_value)) {
62
+ Check_Type(rb_value, T_FIXNUM);
63
+ opts->min_line = FIX2UINT(rb_value);
64
+ }
65
+
66
+ rb_value = rb_hash_aref(rb_options, CSTR2SYM("max_line"));
67
+ if (!NIL_P(rb_value)) {
68
+ Check_Type(rb_value, T_FIXNUM);
69
+ opts->max_line = FIX2UINT(rb_value);
70
+ }
71
+
72
+ rb_value = rb_hash_aref(rb_options, CSTR2SYM("newest_commit"));
73
+ if (!NIL_P(rb_value)) {
74
+ int error = rugged_oid_get(&opts->newest_commit, repo, rb_value);
75
+ rugged_exception_check(error);
76
+ }
77
+
78
+ rb_value = rb_hash_aref(rb_options, CSTR2SYM("oldest_commit"));
79
+ if (!NIL_P(rb_value)) {
80
+ int error = rugged_oid_get(&opts->oldest_commit, repo, rb_value);
81
+ rugged_exception_check(error);
82
+ }
83
+
84
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("track_copies_same_file")))) {
85
+ opts->flags |= GIT_BLAME_TRACK_COPIES_SAME_FILE;
86
+ }
87
+
88
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("track_copies_same_commit_moves")))) {
89
+ opts->flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES;
90
+ }
91
+
92
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("track_copies_same_commit_copies")))) {
93
+ opts->flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES;
94
+ }
95
+
96
+ if (RTEST(rb_hash_aref(rb_options, CSTR2SYM("track_copies_any_commit_copies")))) {
97
+ opts->flags |= GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES;
98
+ }
99
+ }
100
+ }
101
+
102
+ /*
103
+ * call-seq:
104
+ * Blame.new(repo, path, options = {}) -> blame
105
+ *
106
+ * Get blame data for the file at +path+ in +repo+.
107
+ *
108
+ * The following options can be passed in the +options+ Hash:
109
+ *
110
+ * :newest_commit ::
111
+ * The ID of the newest commit to consider in the blame. Defaults to +HEAD+.
112
+ * This can either be a Rugged::Object instance, or a full or abbreviated
113
+ * SHA1 id.
114
+ *
115
+ * :oldest_commit ::
116
+ * The id of the oldest commit to consider. Defaults to the first commit
117
+ * encountered with a NULL parent. This can either be a Rugged::Object
118
+ * instance, or a full or abbreviated SHA1 id.
119
+ *
120
+ * :min_line ::
121
+ * The first line in the file to blame. Line numbers start with 1.
122
+ * Defaults to +1+.
123
+ *
124
+ * :max_line ::
125
+ * The last line in the file to blame. Defaults to the last line in
126
+ * the file.
127
+ *
128
+ * :track_copies_same_file
129
+ * If this value is +true+, lines that have moved within a file will be
130
+ * tracked (like `git blame -M`).
131
+ *
132
+ * :track_copies_same_commit_moves
133
+ * If this value is +true+, lines that have moved across files in the same
134
+ * commit will be tracked (like `git blame -C`).
135
+ *
136
+ * :track_copies_same_commit_copies
137
+ * If this value is +true+, lines that have been copied from another file
138
+ * that exists in the same commit will be tracked (like `git blame -CC`).
139
+ *
140
+ * :track_copies_any_commit_copies
141
+ * If this value is +true+, lines that have been copied from another file
142
+ * that exists in *any* commit will be tracked (like `git blame -CCC`).
143
+ *
144
+ */
145
+ static VALUE rb_git_blame_new(int argc, VALUE *argv, VALUE klass)
146
+ {
147
+ VALUE rb_repo, rb_path, rb_options;
148
+ git_repository *repo;
149
+ git_blame *blame;
150
+ git_blame_options opts = GIT_BLAME_OPTIONS_INIT;
151
+
152
+ rb_scan_args(argc, argv, "20:", &rb_repo, &rb_path, &rb_options);
153
+
154
+ rugged_check_repo(rb_repo);
155
+ Data_Get_Struct(rb_repo, git_repository, repo);
156
+
157
+ Check_Type(rb_path, T_STRING);
158
+
159
+ rugged_parse_blame_options(&opts, repo, rb_options);
160
+
161
+ rugged_exception_check(git_blame_file(
162
+ &blame, repo, StringValueCStr(rb_path), &opts
163
+ ));
164
+
165
+ return Data_Wrap_Struct(klass, NULL, &git_blame_free, blame);
166
+ }
167
+
168
+ /*
169
+ * call-seq:
170
+ * blame.for_line(line_no) -> hunk
171
+ *
172
+ * Returns the blame hunk data for the given +line_no+ in +blame+.
173
+ * Line number counting starts with +1+.
174
+ */
175
+ static VALUE rb_git_blame_for_line(VALUE self, VALUE rb_line_no)
176
+ {
177
+ git_blame *blame;
178
+ int line_no;
179
+
180
+ Data_Get_Struct(self, git_blame, blame);
181
+ Check_Type(rb_line_no, T_FIXNUM);
182
+
183
+ line_no = NUM2INT(rb_line_no);
184
+
185
+ if (line_no < 0) {
186
+ rb_raise(rb_eArgError, "line number can't be negative");
187
+ }
188
+
189
+ return rb_git_blame_hunk_fromC(
190
+ git_blame_get_hunk_byline(blame, (uint32_t)line_no)
191
+ );
192
+ }
193
+
194
+ /*
195
+ * call-seq:
196
+ * blame.count -> count
197
+ * blame.size -> count
198
+ *
199
+ * Returns the total +count+ of blame hunks in +blame+.
200
+ */
201
+ static VALUE rb_git_blame_count(VALUE self)
202
+ {
203
+ git_blame *blame;
204
+ Data_Get_Struct(self, git_blame, blame);
205
+ return UINT2NUM(git_blame_get_hunk_count(blame));
206
+ }
207
+
208
+ /*
209
+ * call-seq:
210
+ * blame[index] -> hunk
211
+ *
212
+ * Returns the blame hunk data at the given +index+ in +blame+.
213
+ *
214
+ * Negative indices count backward from the end of the blame hunks (-1 is the last
215
+ * element).
216
+ *
217
+ * Returns +nil+ if no blame hunk exists at the given +index+.
218
+ */
219
+ static VALUE rb_git_blame_get_by_index(VALUE self, VALUE rb_index)
220
+ {
221
+ git_blame *blame;
222
+ int index;
223
+ uint32_t blame_count;
224
+
225
+ Data_Get_Struct(self, git_blame, blame);
226
+ Check_Type(rb_index, T_FIXNUM);
227
+
228
+ index = NUM2INT(rb_index);
229
+ blame_count = git_blame_get_hunk_count(blame);
230
+
231
+ if (index < 0) {
232
+ if ((uint32_t)(-index) > blame_count) {
233
+ return Qnil;
234
+ }
235
+
236
+ return rb_git_blame_hunk_fromC(
237
+ git_blame_get_hunk_byindex(blame, (uint32_t)(blame_count + index))
238
+ );
239
+ }
240
+
241
+ if ((uint32_t)index > blame_count)
242
+ return Qnil;
243
+
244
+ return rb_git_blame_hunk_fromC(
245
+ git_blame_get_hunk_byindex(blame, (uint32_t)index)
246
+ );
247
+ }
248
+
249
+ /*
250
+ * call-seq:
251
+ * blame.each { |hunk| ... } -> blame
252
+ * blame.each -> enumerator
253
+ *
254
+ * If given a block, yields each +hunk+ that is part of +blame+.
255
+ * If no block is given, an enumerator will be returned.
256
+ */
257
+ static VALUE rb_git_blame_each(VALUE self)
258
+ {
259
+ git_blame *blame;
260
+ uint32_t i, blame_count;
261
+
262
+ if (!rb_block_given_p()) {
263
+ return rb_funcall(self, rb_intern("to_enum"), 1, CSTR2SYM("each"), self);
264
+ }
265
+
266
+ Data_Get_Struct(self, git_blame, blame);
267
+
268
+ blame_count = git_blame_get_hunk_count(blame);
269
+ for (i = 0; i < blame_count; ++i) {
270
+ rb_yield(rb_git_blame_hunk_fromC(
271
+ git_blame_get_hunk_byindex(blame, i)
272
+ ));
273
+ }
274
+
275
+ return self;
276
+ }
277
+
278
+ void Init_rugged_blame(void)
279
+ {
280
+ rb_cRuggedBlame = rb_define_class_under(rb_mRugged, "Blame", rb_cObject);
281
+ rb_include_module(rb_cRuggedBlame, rb_mEnumerable);
282
+
283
+ rb_define_singleton_method(rb_cRuggedBlame, "new", rb_git_blame_new, -1);
284
+
285
+ rb_define_method(rb_cRuggedBlame, "[]", rb_git_blame_get_by_index, 1);
286
+ rb_define_method(rb_cRuggedBlame, "for_line", rb_git_blame_for_line, 1);
287
+
288
+ rb_define_method(rb_cRuggedBlame, "count", rb_git_blame_count, 0);
289
+ rb_define_method(rb_cRuggedBlame, "size", rb_git_blame_count, 0);
290
+
291
+ rb_define_method(rb_cRuggedBlame, "each", rb_git_blame_each, 0);
292
+ }