rdavila-rugged 0.24.0b13

Sign up to get free protection for your applications and to get access to all the features.
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,384 @@
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
+ extern VALUE rb_cRuggedSubmodule;
29
+ VALUE rb_cRuggedSubmoduleCollection;
30
+
31
+ /*
32
+ * call-seq:
33
+ * SubmoduleCollection.new(repo) -> submodules
34
+ *
35
+ * Creates and returns a new collection of submodules for the given +repo+.
36
+ */
37
+ static VALUE rb_git_submodule_collection_initialize(VALUE self, VALUE rb_repo)
38
+ {
39
+ rugged_check_repo(rb_repo);
40
+ rugged_set_owner(self, rb_repo);
41
+ return self;
42
+ }
43
+
44
+ static void rb_git_submodule__free(git_submodule *submodule)
45
+ {
46
+ git_submodule_free(submodule);
47
+ }
48
+
49
+ VALUE rugged_submodule_new(VALUE owner, git_submodule *submodule)
50
+ {
51
+ VALUE rb_submodule;
52
+
53
+ rb_submodule = Data_Wrap_Struct(
54
+ rb_cRuggedSubmodule,
55
+ NULL,
56
+ &rb_git_submodule__free,
57
+ submodule);
58
+ rugged_set_owner(rb_submodule, owner);
59
+
60
+ return rb_submodule;
61
+ }
62
+
63
+ /*
64
+ * call-seq:
65
+ * submodules[name] -> submodule or nil
66
+ *
67
+ * Lookup +submodule+ by +name+ or +path+ (they are usually the same) in
68
+ * +repository+.
69
+ *
70
+ * Returns +nil+ if submodule does not exist.
71
+ *
72
+ * Raises <tt>Rugged::SubmoduleError</tt> if submodule exists only in working
73
+ * directory (i.e. there is a subdirectory that is a valid self-contained git
74
+ * repository) and is not mentioned in the +HEAD+, the index and the config.
75
+ */
76
+ static VALUE rb_git_submodule_collection_aref(VALUE self, VALUE rb_name)
77
+ {
78
+ git_repository *repo;
79
+ git_submodule *submodule;
80
+ int error;
81
+
82
+ VALUE rb_repo = rugged_owner(self);
83
+ Data_Get_Struct(rb_repo, git_repository, repo);
84
+
85
+ Check_Type(rb_name, T_STRING);
86
+
87
+ error = git_submodule_lookup(
88
+ &submodule,
89
+ repo,
90
+ StringValueCStr(rb_name)
91
+ );
92
+
93
+ if (error == GIT_ENOTFOUND)
94
+ return Qnil;
95
+
96
+ rugged_exception_check(error);
97
+
98
+ return rugged_submodule_new(rb_repo, submodule);
99
+ }
100
+
101
+ static int cb_submodule__each(git_submodule *submodule, const char *name, void *data)
102
+ {
103
+ struct rugged_cb_payload *payload = data;
104
+ git_repository *repo;
105
+ git_submodule *dummy_sm;
106
+ VALUE rb_repo;
107
+
108
+ rb_repo = payload->rb_data;
109
+ Data_Get_Struct(rb_repo, git_repository, repo);
110
+
111
+ /* The submodule passed here has it's refcount decreased just after
112
+ * the foreach finishes. The only way to increase that refcount is
113
+ * to lookup the submodule.
114
+ *
115
+ * This should not return an error as the submodule name here is valid
116
+ * and exists, as it was just passed to this callback.
117
+ */
118
+ git_submodule_lookup(&dummy_sm, repo, git_submodule_name(submodule));
119
+
120
+ rb_protect(
121
+ rb_yield,
122
+ rugged_submodule_new(rb_repo, dummy_sm),
123
+ &payload->exception
124
+ );
125
+ return (payload->exception) ? GIT_ERROR : GIT_OK;
126
+ }
127
+
128
+ /*
129
+ * call-seq:
130
+ * submodules.each { |submodule| block }
131
+ * submodules.each -> enumerator
132
+ *
133
+ * Iterate through all the tracked submodules in the collection's +repository+.
134
+ *
135
+ * The given +block+ will be called once with each +submodule+
136
+ * as a Rugged::Submodule instance.
137
+ * If no block is given, an enumerator will be returned.
138
+ */
139
+ static VALUE rb_git_submodule_collection_each(VALUE self)
140
+ {
141
+ git_repository *repo;
142
+ int error;
143
+ struct rugged_cb_payload payload;
144
+
145
+ VALUE rb_repo = rugged_owner(self);
146
+ Data_Get_Struct(rb_repo, git_repository, repo);
147
+
148
+ if (!rb_block_given_p())
149
+ return rb_funcall(self, rb_intern("to_enum"), 1, CSTR2SYM("each"));
150
+
151
+ payload.exception = 0;
152
+ payload.rb_data = rb_repo;
153
+
154
+ error = git_submodule_foreach(repo, &cb_submodule__each, &payload);
155
+
156
+ if (payload.exception)
157
+ rb_jump_tag(payload.exception);
158
+ rugged_exception_check(error);
159
+
160
+ return Qnil;
161
+ }
162
+
163
+ /*
164
+ * call-seq:
165
+ * submodules.setup_add(url, path[, options]) -> submodule
166
+ *
167
+ * Setup a new +submodule+ for checkout in +repository+.
168
+ *
169
+ * This does <tt>"git submodule add"</tt> up to the fetch and checkout of the
170
+ * submodule contents. It prepares a new submodule, creates an entry in
171
+ * +.gitmodules+ and creates an empty initialized repository either at the
172
+ * given +path+ in the working directory or in +.git/modules+ with a gitlink
173
+ * from the working directory to the new repository.
174
+ *
175
+ * To fully emulate <tt>"git submodule add"</tt> call this function, then open
176
+ * the submodule repository and perform the clone step as needed.
177
+ * Lastly, call Submodule#finalize_add to wrap up adding the new submodule and
178
+ * +.gitmodules+ to the index to be ready to commit.
179
+ *
180
+ * - +url+: URL for the submodule's remote
181
+ * - +path+: path at which the submodule should be created
182
+ *
183
+ * The following options can be passed in the +options+ Hash:
184
+ * :gitlink ::
185
+ * (defaults to +true+) should workdir contain a
186
+ * gitlink to the repository in +.git/modules+ vs. repository
187
+ * directly in workdir.
188
+ *
189
+ * Returns the newly created +submodule+
190
+ */
191
+ static VALUE rb_git_submodule_setup_add(int argc, VALUE *argv, VALUE self)
192
+ {
193
+ git_submodule *submodule;
194
+ git_repository *repo;
195
+ int error;
196
+ int use_gitlink = 1;
197
+ VALUE rb_repo, rb_url, rb_path, rb_options;
198
+
199
+ rb_scan_args(argc, argv, "20:", &rb_url, &rb_path, &rb_options);
200
+
201
+ Check_Type(rb_url, T_STRING);
202
+ Check_Type(rb_path, T_STRING);
203
+
204
+ rb_repo = rugged_owner(self);
205
+ Data_Get_Struct(rb_repo, git_repository, repo);
206
+
207
+ if (!NIL_P(rb_options)) {
208
+ VALUE rb_val;
209
+
210
+ rb_val = rb_hash_aref(rb_options, CSTR2SYM("gitlink"));
211
+ use_gitlink = (rb_val != Qfalse);
212
+ }
213
+
214
+ error = git_submodule_add_setup(
215
+ &submodule,
216
+ repo,
217
+ StringValueCStr(rb_url),
218
+ StringValueCStr(rb_path),
219
+ use_gitlink
220
+ );
221
+
222
+ rugged_exception_check(error);
223
+
224
+ return rugged_submodule_new(rb_repo, submodule);
225
+ }
226
+
227
+ static git_submodule_ignore_t rb_git_subm_ignore_rule_toC(VALUE rb_ignore_rule)
228
+ {
229
+ ID id_ignore_rule;
230
+
231
+ Check_Type(rb_ignore_rule, T_SYMBOL);
232
+ id_ignore_rule = SYM2ID(rb_ignore_rule);
233
+
234
+ if (id_ignore_rule == rb_intern("none")) {
235
+ return GIT_SUBMODULE_IGNORE_NONE;
236
+ } else if (id_ignore_rule == rb_intern("untracked")) {
237
+ return GIT_SUBMODULE_IGNORE_UNTRACKED;
238
+ } else if (id_ignore_rule == rb_intern("dirty")) {
239
+ return GIT_SUBMODULE_IGNORE_DIRTY;
240
+ } else if (id_ignore_rule == rb_intern("all")) {
241
+ return GIT_SUBMODULE_IGNORE_ALL;
242
+ } else {
243
+ rb_raise(rb_eArgError, "Invalid submodule ignore rule type.");
244
+ }
245
+ }
246
+
247
+ static git_submodule_update_t rb_git_subm_update_rule_toC(VALUE rb_update_rule)
248
+ {
249
+ ID id_update_rule;
250
+
251
+ Check_Type(rb_update_rule, T_SYMBOL);
252
+ id_update_rule = SYM2ID(rb_update_rule);
253
+
254
+ if (id_update_rule == rb_intern("checkout")) {
255
+ return GIT_SUBMODULE_UPDATE_CHECKOUT;
256
+ } else if (id_update_rule == rb_intern("rebase")) {
257
+ return GIT_SUBMODULE_UPDATE_REBASE;
258
+ } else if (id_update_rule == rb_intern("merge")) {
259
+ return GIT_SUBMODULE_UPDATE_MERGE;
260
+ } else if (id_update_rule == rb_intern("none")) {
261
+ return GIT_SUBMODULE_UPDATE_NONE;
262
+ } else {
263
+ rb_raise(rb_eArgError, "Invalid submodule update rule type.");
264
+ }
265
+ }
266
+
267
+ /*
268
+ * call-seq:
269
+ * submodules.update(submodule, settings) -> nil
270
+ * submodules.update(name, settings) -> nil
271
+ *
272
+ * Update settings for the given submodule in the submodule config.
273
+ *
274
+ * Existing `Rugged::Submodule` instances are not updated, but can be
275
+ * reloaded by calling `#reload`.
276
+ *
277
+ * The following options can be passed in the +settings+ Hash:
278
+ *
279
+ * :url ::
280
+ * Updates the URL for the submodule.
281
+ *
282
+ * :ignore_rule ::
283
+ * See `Rugged::Submodule#ignore_rule` for a list of accepted rules.
284
+ *
285
+ * :update_rule ::
286
+ * See `Rugged::Submodule#update_rule` for a list of accepted rules.
287
+ *
288
+ * :fetch_recurse_submodules ::
289
+ * Updates the +fetchRecurseSubmodules+ rule.
290
+ */
291
+ static VALUE rb_git_submodule_update(VALUE self, VALUE rb_name_or_submodule, VALUE rb_settings)
292
+ {
293
+ git_repository *repo;
294
+ git_submodule_ignore_t ignore_rule = GIT_SUBMODULE_IGNORE_UNSPECIFIED;
295
+ git_submodule_update_t update_rule = GIT_SUBMODULE_UPDATE_DEFAULT;
296
+ const char *submodule_name;
297
+ int fetch_recurse_submodules = 0;
298
+ VALUE rb_repo = rugged_owner(self);
299
+ VALUE rb_url, rb_fetch_recurse_submodules, rb_ignore_rule, rb_update_rule;
300
+
301
+ rugged_check_repo(rb_repo);
302
+ Data_Get_Struct(rb_repo, git_repository, repo);
303
+
304
+ if (rb_obj_is_kind_of(rb_name_or_submodule, rb_cRuggedSubmodule))
305
+ rb_name_or_submodule = rb_funcall(rb_name_or_submodule, rb_intern("name"), 0);
306
+
307
+ if (TYPE(rb_name_or_submodule) != T_STRING)
308
+ rb_raise(rb_eTypeError, "Expecting a String or Rugged::Submodule instance");
309
+
310
+ rb_url = rb_hash_aref(rb_settings, CSTR2SYM("url"));
311
+ rb_fetch_recurse_submodules = rb_hash_aref(rb_settings, CSTR2SYM("fetch_recurse_submodules"));
312
+ rb_ignore_rule = rb_hash_aref(rb_settings, CSTR2SYM("ignore_rule"));
313
+ rb_update_rule = rb_hash_aref(rb_settings, CSTR2SYM("update_rule"));
314
+
315
+ if (!NIL_P(rb_url)) {
316
+ Check_Type(rb_url, T_STRING);
317
+ }
318
+
319
+ if (!NIL_P(rb_fetch_recurse_submodules)) {
320
+ fetch_recurse_submodules = rugged_parse_bool(rb_fetch_recurse_submodules);
321
+ }
322
+
323
+ if (!NIL_P(rb_ignore_rule)) {
324
+ ignore_rule = rb_git_subm_ignore_rule_toC(rb_ignore_rule);
325
+ }
326
+
327
+ if (!NIL_P(rb_update_rule)) {
328
+ update_rule = rb_git_subm_update_rule_toC(rb_update_rule);
329
+ }
330
+
331
+ submodule_name = StringValueCStr(rb_name_or_submodule);
332
+
333
+ if (!NIL_P(rb_url)) {
334
+ rugged_exception_check(
335
+ git_submodule_set_url(repo,
336
+ submodule_name,
337
+ StringValueCStr(rb_url)
338
+ )
339
+ );
340
+ }
341
+
342
+ if (!NIL_P(rb_fetch_recurse_submodules)) {
343
+ rugged_exception_check(
344
+ git_submodule_set_fetch_recurse_submodules(repo,
345
+ submodule_name,
346
+ fetch_recurse_submodules
347
+ )
348
+ );
349
+ }
350
+
351
+ if (!NIL_P(rb_ignore_rule)) {
352
+ rugged_exception_check(
353
+ git_submodule_set_ignore(repo,
354
+ submodule_name,
355
+ ignore_rule
356
+ )
357
+ );
358
+ }
359
+
360
+ if (!NIL_P(rb_update_rule)) {
361
+ rugged_exception_check(
362
+ git_submodule_set_update(repo,
363
+ submodule_name,
364
+ update_rule
365
+ )
366
+ );
367
+ }
368
+
369
+ return Qnil;
370
+ }
371
+
372
+ void Init_rugged_submodule_collection(void)
373
+ {
374
+ rb_cRuggedSubmoduleCollection = rb_define_class_under(rb_mRugged, "SubmoduleCollection", rb_cObject);
375
+ rb_include_module(rb_cRuggedSubmoduleCollection, rb_mEnumerable);
376
+
377
+ rb_define_method(rb_cRuggedSubmoduleCollection, "initialize", rb_git_submodule_collection_initialize, 1);
378
+ rb_define_method(rb_cRuggedSubmoduleCollection, "[]", rb_git_submodule_collection_aref, 1);
379
+ rb_define_method(rb_cRuggedSubmoduleCollection, "each", rb_git_submodule_collection_each, 0);
380
+
381
+ rb_define_method(rb_cRuggedSubmoduleCollection, "update", rb_git_submodule_update, 2);
382
+
383
+ rb_define_method(rb_cRuggedSubmoduleCollection, "setup_add", rb_git_submodule_setup_add, -1);
384
+ }
@@ -0,0 +1,251 @@
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
+ extern VALUE rb_cRuggedObject;
29
+ extern VALUE rb_cRuggedRepo;
30
+ extern VALUE rb_cRuggedReference;
31
+
32
+ VALUE rb_cRuggedTag;
33
+ VALUE rb_cRuggedTagAnnotation;
34
+
35
+ /*
36
+ * call-seq:
37
+ * annotation.target -> object
38
+ *
39
+ * Return the +object+ pointed at by this tag annotation, as a <tt>Rugged::Object</tt>
40
+ * instance.
41
+ *
42
+ * annotation.target #=> #<Rugged::Commit:0x108828918>
43
+ */
44
+ static VALUE rb_git_tag_annotation_target(VALUE self)
45
+ {
46
+ git_tag *tag;
47
+ git_object *target;
48
+ int error;
49
+ VALUE owner;
50
+
51
+ Data_Get_Struct(self, git_tag, tag);
52
+ owner = rugged_owner(self);
53
+
54
+ error = git_tag_target(&target, tag);
55
+ rugged_exception_check(error);
56
+
57
+ return rugged_object_new(owner, target);
58
+ }
59
+
60
+ /*
61
+ * call-seq:
62
+ * annotation.target_oid -> oid
63
+ * annotation.target_id -> oid
64
+ *
65
+ * Return the oid pointed at by this tag annotation, as a <tt>String</tt>
66
+ * instance.
67
+ *
68
+ * annotation.target_id #=> "2cb831a8aea28b2c1b9c63385585b864e4d3bad1"
69
+ */
70
+ static VALUE rb_git_tag_annotation_target_id(VALUE self)
71
+ {
72
+ git_tag *tag;
73
+ const git_oid *target_oid;
74
+
75
+ Data_Get_Struct(self, git_tag, tag);
76
+
77
+ target_oid = git_tag_target_id(tag);
78
+
79
+ return rugged_create_oid(target_oid);
80
+ }
81
+
82
+ /*
83
+ * call-seq:
84
+ * annotation.type -> t
85
+ *
86
+ * Return a symbol representing the type of the objeced pointed at by
87
+ * this +annotation+. Possible values are +:blob+, +:commit+, +:tree+ and +:tag+.
88
+ *
89
+ * This is always the same as the +type+ of the returned <tt>annotation.target</tt>
90
+ *
91
+ * annotation.type #=> :commit
92
+ * annotation.target.type == annotation.type #=> true
93
+ */
94
+ static VALUE rb_git_tag_annotation_target_type(VALUE self)
95
+ {
96
+ git_tag *tag;
97
+ Data_Get_Struct(self, git_tag, tag);
98
+
99
+ return rugged_otype_new(git_tag_target_type(tag));
100
+ }
101
+
102
+ /*
103
+ * call-seq:
104
+ * annotation.name -> name
105
+ *
106
+ * Return a string with the name of this tag +annotation+.
107
+ *
108
+ * annotation.name #=> "v0.16.0"
109
+ */
110
+ static VALUE rb_git_tag_annotation_name(VALUE self)
111
+ {
112
+ git_tag *tag;
113
+ Data_Get_Struct(self, git_tag, tag);
114
+
115
+ return rb_str_new_utf8(git_tag_name(tag));
116
+ }
117
+
118
+ /*
119
+ * call-seq:
120
+ * annotation.tagger -> signature
121
+ *
122
+ * Return the signature for the author of this tag +annotation+. The signature
123
+ * is returned as a +Hash+ containing +:name+, +:email+ of the author
124
+ * and +:time+ of the tagging.
125
+ *
126
+ * annotation.tagger #=> {:email=>"tanoku@gmail.com", :time=>Tue Jan 24 05:42:45 UTC 2012, :name=>"Vicent Mart\303\255"}
127
+ */
128
+ static VALUE rb_git_tag_annotation_tagger(VALUE self)
129
+ {
130
+ git_tag *tag;
131
+ const git_signature *tagger;
132
+
133
+ Data_Get_Struct(self, git_tag, tag);
134
+ tagger = git_tag_tagger(tag);
135
+
136
+ if (!tagger)
137
+ return Qnil;
138
+
139
+ return rugged_signature_new(tagger, NULL);
140
+ }
141
+
142
+ /*
143
+ * call-seq:
144
+ * annotation.message -> msg
145
+ *
146
+ * Return the message of this tag +annotation+. This includes the full body of the
147
+ * message and any optional footers or signatures after it.
148
+ *
149
+ * annotation.message #=> "Release v0.16.0, codename 'broken stuff'"
150
+ */
151
+ static VALUE rb_git_tag_annotation_message(VALUE self)
152
+ {
153
+ git_tag *tag;
154
+ const char *message;
155
+
156
+ Data_Get_Struct(self, git_tag, tag);
157
+ message = git_tag_message(tag);
158
+
159
+ if (!message)
160
+ return Qnil;
161
+
162
+ return rb_str_new_utf8(message);
163
+ }
164
+
165
+ /*
166
+ * call-seq:
167
+ * tag.annotation -> annotation or nil
168
+ */
169
+ static VALUE rb_git_tag_annotation(VALUE self)
170
+ {
171
+ git_reference *ref, *resolved_ref;
172
+ git_repository *repo;
173
+ git_object *target;
174
+ int error;
175
+ VALUE rb_repo = rugged_owner(self);
176
+
177
+ rugged_check_repo(rb_repo);
178
+ Data_Get_Struct(self, git_reference, ref);
179
+ Data_Get_Struct(rb_repo, git_repository, repo);
180
+
181
+ error = git_reference_resolve(&resolved_ref, ref);
182
+ rugged_exception_check(error);
183
+
184
+ error = git_object_lookup(&target, repo, git_reference_target(resolved_ref), GIT_OBJ_TAG);
185
+ git_reference_free(resolved_ref);
186
+
187
+ if (error == GIT_ENOTFOUND)
188
+ return Qnil;
189
+
190
+ return rugged_object_new(rb_repo, target);
191
+ }
192
+
193
+ /*
194
+ * call-seq:
195
+ * tag.target -> git_object
196
+ */
197
+ static VALUE rb_git_tag_target(VALUE self)
198
+ {
199
+ git_reference *ref, *resolved_ref;
200
+ git_repository *repo;
201
+ git_object *target;
202
+ int error;
203
+ VALUE rb_repo = rugged_owner(self);
204
+
205
+ rugged_check_repo(rb_repo);
206
+ Data_Get_Struct(self, git_reference, ref);
207
+ Data_Get_Struct(rb_repo, git_repository, repo);
208
+
209
+ error = git_reference_resolve(&resolved_ref, ref);
210
+ rugged_exception_check(error);
211
+
212
+ error = git_object_lookup(&target, repo, git_reference_target(resolved_ref), GIT_OBJ_ANY);
213
+ git_reference_free(resolved_ref);
214
+ rugged_exception_check(error);
215
+
216
+ if (git_object_type(target) == GIT_OBJ_TAG) {
217
+ git_object *annotation_target;
218
+
219
+ error = git_tag_target(&annotation_target, (git_tag *)target);
220
+ git_object_free(target);
221
+ rugged_exception_check(error);
222
+
223
+ return rugged_object_new(rb_repo, annotation_target);
224
+ } else {
225
+ return rugged_object_new(rb_repo, target);
226
+ }
227
+ }
228
+
229
+ static VALUE rb_git_tag_annotated_p(VALUE self)
230
+ {
231
+ return RTEST(rb_git_tag_annotation(self)) ? Qtrue : Qfalse;
232
+ }
233
+
234
+ void Init_rugged_tag(void)
235
+ {
236
+ rb_cRuggedTag = rb_define_class_under(rb_mRugged, "Tag", rb_cRuggedReference);
237
+
238
+ rb_define_method(rb_cRuggedTag, "annotation", rb_git_tag_annotation, 0);
239
+ rb_define_method(rb_cRuggedTag, "annotated?", rb_git_tag_annotated_p, 0);
240
+ rb_define_method(rb_cRuggedTag, "target", rb_git_tag_target, 0);
241
+
242
+ rb_cRuggedTagAnnotation = rb_define_class_under(rb_cRuggedTag, "Annotation", rb_cRuggedObject);
243
+
244
+ rb_define_method(rb_cRuggedTagAnnotation, "message", rb_git_tag_annotation_message, 0);
245
+ rb_define_method(rb_cRuggedTagAnnotation, "name", rb_git_tag_annotation_name, 0);
246
+ rb_define_method(rb_cRuggedTagAnnotation, "target", rb_git_tag_annotation_target, 0);
247
+ rb_define_method(rb_cRuggedTagAnnotation, "target_oid", rb_git_tag_annotation_target_id, 0);
248
+ rb_define_method(rb_cRuggedTagAnnotation, "target_id", rb_git_tag_annotation_target_id, 0);
249
+ rb_define_method(rb_cRuggedTagAnnotation, "target_type", rb_git_tag_annotation_target_type, 0);
250
+ rb_define_method(rb_cRuggedTagAnnotation, "tagger", rb_git_tag_annotation_tagger, 0);
251
+ }